码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 1296E1 - String Coloring (easy version)

时间:2020-02-05 09:53:43      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:ring   最大   通过   说明   字典   mes   组成   代码   返回   

题目大意:

给定一段长度为n的字符串s

你需要给每个字符进行涂色,然后相邻的不同色的字符可以进行交换

需要保证涂色后能通过相邻交换把这个字符串按照字典序排序(a~z)

你只有两种颜色可以用来涂

问是否存在这么一种涂色方案满足题意

存在,输出YES,再用01表示两种不同的颜色,把涂色方案输出(如果有多种,输出任意一种)

不存在,输出NO

 

解题思路 1:

因为只有两种颜色可以用来涂

相同颜色彼此不能交换

所以同一种颜色组成的序列绝对是非严格递增的

那么就用mx记录一种颜色代表的非严格递增的序列到某个位置时的最大字符,pmx记录另一种颜色代表的到某个位置时的最大字符

只要在找第一种颜色时出现了一个比最大值小的,就把他推给第二种颜色

如果也比第二种颜色最大值小,说明至少得三种颜色才能满足,此情况直接输出NO

就可以得到以下代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 void solve(){
 4     int n,i;
 5     string s,ans="";
 6     cin>>n>>s;
 7     char mx=a,pmx=a;
 8     for(i=0;i<n;i++){
 9         if(s[i]>=mx){
10             mx=max(mx,s[i]);
11             ans+="0";
12         }
13         else{
14             if(pmx<=s[i]){
15                 ans+="1";
16                 pmx=max(pmx,s[i]);
17             }
18             else{
19                 cout<<"NO\n";
20                 return;
21             }
22         }
23     }
24     cout<<"YES\n"<<ans;
25 }
26 int main(){
27     ios::sync_with_stdio(0);
28     cin.tie(0);cout.tie(0);
29     solve();
30     
31     return 0;
32 }

 

解题思路 2:

※该思路可直接用于题 E2 hard 版本

可以引入一个 r 数组,开26个空间代表26种字母

这个数组 r[i] 的值代表 第 i 个字母在前面涂的颜色最大编号是多少,0表示没出现过

遍历这个字符串,每遍历到一个字母时,从当前字母后一个位置开始往后再遍历这个数组,即找比当前字母要大的所有字母中编号最大的那个字母的编号

根据解题思路1,如果一个字符比一种颜色最大值要小,那么就把它推给下一种颜色

如果这个过程所有颜色都按照从1开始递增的顺序来,那么,这个字符的颜色编号会比前面的比他大的字符中编号最大的那个编号还要大

就可以得出结论,每次找比当前字母大的所有字母中涂色方案最大的编号+1,即为当前字母涂色方案

只要涂色方案出现大于2种,直接输出NO

代码实现如下

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 void solve(){
 4     int n,i,j,d,r[26]={0};
 5     string s;
 6     cin>>n>>s;
 7     string ans;
 8     for(i=0;i<n;i++){
 9         d=1;
10         for(j=s[i]-a+1;j<26;j++)//从当前字母后一个位置开始往后找
11             d=max(d,r[j]+1);
12         r[s[i]-a]=d;
13         if(d>2){
14             cout<<"NO";
15             return;
16         }
17         ans+=((d-1)?"1":"0");
18     }
19     cout<<"YES\n"<<ans;
20 }
21 int main(){
22     ios::sync_with_stdio(0);
23     cin.tie(0);cout.tie(0);
24     solve();
25     
26     return 0;
27 }

 

解题思路 3:

※该思路可直接用于题 E2 hard 版本

因为相同颜色彼此不能交换,所以必定是已经有顺序的

那么就可以得到这一种想法,编号从1开始,从头到尾遍历出一条非严格递增的标记为颜色0,如果标记出来的数量和小于n(即还有一些字符没有被标记),那么就加一种颜色,重新再来一遍,如果还是没有全部涂起来,说明颜色至少要3种,直接返回NO

实测方案可行,代码如下

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 void solve(){
 4     int n,i,done=0,cur=0;
 5     char mx;
 6     string s;
 7     cin>>n>>s;
 8     vector<int> ans(n,-1);
 9     while(done<n){
10         mx=a;
11         if(cur>1){
12             cout<<"NO";
13             return;
14         }
15         for(i=0;i<n;i++){
16             if(ans[i]==-1&&s[i]>=mx){
17                 mx=s[i];
18                 done++;
19                 ans[i]=cur;
20             }
21         }
22         cur++;
23     }
24     cout<<"YES\n";
25     for(i=0;i<n;i++)
26         cout<<ans[i];
27 }
28 int main(){
29     ios::sync_with_stdio(0);
30     cin.tie(0);cout.tie(0);
31     solve();
32     
33     return 0;
34 }

 

Codeforces 1296E1 - String Coloring (easy version)

标签:ring   最大   通过   说明   字典   mes   组成   代码   返回   

原文地址:https://www.cnblogs.com/stelayuri/p/12262352.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!