博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Codeforces Round #617 (Div. 3) String Coloring(E1.E2)
阅读量:3965 次
发布时间:2019-05-24

本文共 3647 字,大约阅读时间需要 12 分钟。

(easy version):

题目链接:

 

题目一句话就是说,两种颜色不同的字符可以相互换位,

问,对这字符串用最多两种颜色染色,然后经过有限次换位

可以变成字典序排序的顺序。

 

思路:一个字符需不需要换位,应该是参照最后的字典序的顺序,

那么,我们应该给字符串排序,再去思考问题。

我们知道,如果str[now_i]的位置和排序后的位置不一样,那就是需要换位。

我们还知道,如果str[now_i]的当前位置如果小于等于排序后的位置,

说明str[now_i]会往后移动,之前应该是会多出(>=0)个字符,那么我们不妨

让str[now_i]不主动移动(标记‘0’),让str[now_x]当前位置大于排序后位置的去向前主动移动(也必须向前移动)(标记‘1’),

那么经过一些str[now_x]向前移动,str[now_i]会被动的回到排序后的位置,从而达到"YES"。

那什么情况是“NO”?

如果我们标记的'1'字符组成的字符串出现了"ba",”bca”,就是说不满足非递减性质,

那么"ba",a是'1',b也是'1',就是说,a不可能到b前面,那也就是“NO”了,举个样例:

7

abcdedc

0000011

撇开这个样例不管,如果出现了"ba",如果把要b换成'0',那么之前本该属于b位置的需要变成'1',

使得可以和b转位,但是被换成'1'的那个字符又导致'a'不能回到a本该属于的位置,所以这个情况是''NO"就证明成立了,也间接证明了"YES"情况的正确性,所以方法猜想正确,之后的做法就只需要维护这个方法就行。

时间复杂度可以是O(n)

1 #include 
2 #include
3 #include
4 #include
5 #include
6 using namespace std; 7 8 struct Info{ 9 queue
index;10 void pb(int x){ index.push(x); }11 int loc(){ int x = index.front(); index.pop(); return x; }12 }info[30];//存储不同字符出现的位置13 14 int main(){15 16 string str;17 int a[500];18 int col[500];//颜色19 int n;20 cin >> n >> str;21 for(int i = 0; i < n;++i) a[i] = str[i]-'a';//字符转化为数字22 sort(a,a+n);//排序23 for(int i = 0; i < n; ++i) info[a[i]].pb(i);//把该字符出现的位置记录24 char error[10] = "aa";//error[0]存储的是不需要主动移动的字符最大是哪个25 //error[1]存储的是需要主动移动的字符最大的是哪个26 for(int now = 0; now < n; ++now){ //now表示当前位置27 int after = info[str[now]-'a'].loc();//取一个该字符排序后的位置28 if(now <= after){ //当前位置小于等于排序后的位置,这里有个特殊情况,29 //abcdedc①30 //abccdde31 //可以看出第二个d虽然和排序后的位置一样,但是他需要换位32 if(str[now] >= error[0]){33 error[0] = str[now];34 col[now] = 0;35 }else{36 col[now] = 1;37 if(str[now] > error[1]) error[1] = str[now];//①的情况出现需要改变error[1]的字符38 }39 }40 else{41 if(str[now] >= error[1]){42 col[now] = 1;43 error[1] = str[now];44 }else{45 error[1] = '!'; break;46 }47 }48 }49 if(error[0] == '!' || error[1] == '!') cout << "NO\n";50 else{51 cout << "YES\n";52 for(int i = 0; i < n; ++i) cout << col[i];53 cout << endl;54 }55 56 return 0;57 }

 

(hard version):

题目链接:

题目:E1说明了只能用两种颜色去染色,现在是最少用几种颜色去染色,可以完成字典序排序。

思路:再次思考E1的证明情况,如果该字符需要染成'1',那么它们组成的字符串是“单调非递减”的,

而'0'组成的字符串也是“单调非递减”的。于是,我们想到,可以把这个题目抽象成一些数字组成一个序列,

问你该序列最少可以分成几个满足性质“非单调递减”的集合,也就是几种颜色了。

那么E2题目就变得简单了,E1也可以不那么复杂的写了。

最多26个字符,也就是最多26个集合,那么 时间复杂度是O(26*n)。

这里有个细节,我们需要充分利用字符之间的间隔,举个例子:

abacd...

先分成两个集合 :ab  ac,应该把d放在"ac"的后面,这样才能充分能利用字符之间的间隔,满足最少颜色。

1 #include 
2 #include
3 #include
4 #include
5 using namespace std; 6 7 const int N = (int)2e5+100; 8 struct node{ 9 int index;10 char ch;11 };12 int col = 0;//集合数13 string str;//每个集合最后的字符14 int ans[N];15 16 int main(){17 18 ios::sync_with_stdio(false);19 cin.tie(0); cout.tie(0);20 int n;21 char ch,max_ch,which_col,len,tmp_ch,now_ch;22 cin >> n;23 for(int i = 0; i < n; ++i){24 cin >> ch;25 which_col = -1;//选哪种颜色26 tmp_ch = 'A';27 for(int j = 0; j < col; ++j){28 now_ch = str[j];29 //选col个集合中最后字符小于等于ch且最接近ch的30 if(now_ch <= ch){31 if(now_ch > tmp_ch){32 tmp_ch = now_ch;33 which_col = j;34 }35 }36 }37 if(which_col != -1){38 str[which_col] = ch;39 ans[i] = which_col+1;40 }41 else{42 //需要新加一种颜色43 str += ch;44 ++col;45 ans[i] = col;46 }47 }48 49 cout << col << endl;50 cout << ans[0];51 for(int i = 1; i < n; ++i) cout << ' ' << ans[i];52 cout << endl;53 54 55 return 0;56 }

 

转载地址:http://wbuki.baihongyu.com/

你可能感兴趣的文章
Java EE 精萃
查看>>
Open Source 精萃
查看>>
Java EE 简介
查看>>
Weblogic 简介
查看>>
观察者模式 (Observer)
查看>>
Java 集合框架
查看>>
Weblogic 精萃
查看>>
Servlet 精萃
查看>>
XStream 精萃
查看>>
XStream 环境设置
查看>>
Git 分支
查看>>
Git 冲突
查看>>
Git Merging vs. Rebasing
查看>>
[第9课] 箱线图
查看>>
[第10课] 箱线图2
查看>>
[第11课]统计:集中趋势
查看>>
[第12课] 统计:样本和总体
查看>>
[第13课] 统计:总体方差
查看>>
[第14课] 统计:样本方差
查看>>
[第15课] 统计:标准差
查看>>