15

20201003国庆模拟

 3 years ago
source link: http://www.cnblogs.com/zdxx/p/13764285.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

T1

求对S进行不超过k次“交换两个相邻的字符”操作,得到的字典序最小的字符串。

95pts:模拟即可。从每个位置出发,找出接下来k个字符中最小的移到前面。每次swap时k--直到k=0。时间复杂度 \(O(n^2)\)

#include<bits/stdc++.h>
using namespace std;
//struct node{
//	int pos,dis;
//	char num;
//}s[1005];
//bool cmp(node a,node b){
//	if(a.num==b.num)return a.pos<b.pos;
//	return a.num<b.num;
//}
int n,k;
char cc[1005];
int main(){
	scanf("%d%d\n",&n,&k);
//	for(int i=1;i<=n;i++){
//		scanf("%c",&cc[i]);
//		s[i].num=cc[i];
//		s[i].pos=i;
//		
//	}
	scanf("%s",cc);
	if(k==0){ 
		for(int i=0;i<n;i++)printf("%c",cc[i]);
		return 0;
	}
	//for(int i=1;i<=n;i++)printf("%c",cc[i]);
	//sort(s+1,s+1+n,cmp);
	//int q=0;
	for(int i=0;i<=n;i++){
			//q++;
			int index=0;
			bool flag=0;
			int tmp=cc[i];
			for(int j=i+1;j<=i+k&&j<n;j++){
				if(tmp>cc[j]){
					tmp=cc[j];
					index=j;
					flag=1;
				}
			}
			if(flag){
				for(int j=index;j>=1;j--){
					if(cc[j]<cc[j-1]){
						swap(cc[j],cc[j-1]);
						k--;
					}
					if(k<=0)break;
				}
				flag=0;
			}
	}
	for(int i=0;i<n;i++)printf("%c",cc[i]);
	return 0;
}

100pts思路:每次选出字典序最小的字母,将它移到前面。若移动次数小于k就直接移动,否则不移动,选择字典序次小的移动。计算移动次数用树状数组维护。时间复杂度 \(O(nlogn)\)

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
const int N=1e6+7,inf=2e9+7;
int head[N],go[N],nxt[N],cnt;
void add(int u,int v){
	go[++cnt]=v;
	nxt[cnt]=head[u];
	head[u]=cnt;
}
int n,s[N];
ll k;
char c[N];
int query(int x){
	int ans=0;
	for(int i=x;i>0;i-=i&-i){
		ans+=s[i];
	}
	return ans;
}
void pluss(int x,int a){
	for(int i=x;i<=n;i+=i&-i){
		s[i]+=a;
	}
}
int ans[N];
int main(){
	//freopen("escape.in","r",stdin);freopen("escape.out","w",stdout);
	scanf("%lld%lld",&n,&k);
	scanf("%s",c+1);
	for(int i=n;i>=1;i--){
		add(c[i]-'a'+1,i);pluss(i,1);
	}
	for(int tmp=0,i=1;i<=n;i++){
		for(int u=1;u<=26;u++,tmp=0){
			if(!head[u])continue;
			if((tmp=query(go[head[u]]-1))<=k){
				pluss(go[head[u]],-1);
				k-=tmp;
				head[u]=nxt[head[u]];
				ans[i]=u;
				break;
			}
		}
	}
	for(int i=1;i<=n;i++)printf("%c",ans[i]+'a'-1);
	return 0;
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK