(easy version):

题目链接:http://codeforces.com/contest/1296/problem/E1

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

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

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

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

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

我们知道,如果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 <iostream>
 2 #include <algorithm>
 3 #include <string>
 4 #include <queue>
 5 #include <cstdio>
 6 using namespace std;
 7
 8 struct Info{
 9     queue<int > 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                         //abccdde
31                         //可以看出第二个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):

题目链接:http://codeforces.com/contest/1296/problem/E2

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

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

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

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

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

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

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

abacd...

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

 1 #include <iostream>
 2 #include <vector>
 3 #include <string>
 4 #include <algorithm>
 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 }

Codeforces Round #617 (Div. 3) String Coloring(E1.E2)相关推荐

  1. Codeforces Round #481 (Div. 3) F. Mentors(思维+二分)

    有 n 个程序员,每个程序员都有他的技能分数,分数严格高的可以做分数低的程序员的老师,但是有 k 对人发生过矛盾,他们不能构成师生关系,问每个人最多可以做几个人的老师 开始想的是开一个数组从 i∈[1 ...

  2. Codeforces Round #518 (Div. 2): F. Knights(神题)

    题意: 一个无限大的棋盘,初始往这个棋盘中放n个骑士(骑士走日字,和马一样),之后如果存在一个点可以被4个骑士一步到达,那么就往这个格子上再放一个马,并且无限继续下去,直到不存在任意一个点可以被4个骑 ...

  3. Codeforces Round #691 (Div. 1) CF1458A-F 题解(待更新)

    第一次打div1,比较自闭.. A. 因为 g c d ( x , y ) = g c d ( x , y − x ) gcd(x,y)=gcd(x,y-x) gcd(x,y)=gcd(x,y−x). ...

  4. Codeforces Round #617 (Div. 3) E2. String Coloring (hard version) 思维 + dp + Dilworth定理

    传送门 文章目录 题意: 思路: 题意: 让你给一个串染色,不同颜色且相邻的一对字符可以互换位置,用最少的颜色,使交换后这个字符串字典序最小. 思路: 考虑将字符串分成若干个非递减的子序列,由于其非递 ...

  5. Codeforces Round #617 (Div. 3) F. Berland Beauty 思维

    传送门 文章目录 题意: 思路: 题意: 给定一棵树,再给定若干两点最短路之间边权的最小值,让你给树的边权赋值,使得满足给定的条件,如果不存在输出−1-1−1. 思路: 观察一个性质,加入经过这条边的 ...

  6. Codeforces Round #774 (Div. 2) Power Board(数学)

    Codeforces Round #774 (Div. 2) Power Board(数学) 链接 题意:给一个n*m的矩阵,每个元素的值是 i j i^j ij,问有多少个不一样的元素 思路:不过这 ...

  7. Ivan the Fool and the Probability Theory-Codeforces Round #594 (Div. 2)-C题(dp+思维)

    Ivan the Fool and the Probability Theory-Codeforces Round #594 (Div. 2)-C题(dp+思维) time limit per tes ...

  8. Codeforces Round #617 (Div. 3)

    A - Array with Odd Sum 题意就是一个数组,你可以把数组中任意一个数变成数组中的另外一个数,让你进行这样的操作,求最后能否使这个数组的和为奇数: 思路: 只要这个数组中存在一个奇数 ...

  9. Codeforces Round #617 (Div. 3)题解全集

    很久没打cf了 被以前经常A不出题支配了 距离上次比赛 大概一个多月了 想着看看这段时间能力提升如何 A题 给你一个数组 可以实现ai 和aj 把aj值赋给ai 问你能不能使得该数组之和是奇数 分析: ...

最新文章

  1. 世界顶级AI大神综述深度学习
  2. python基础指令-python的一些基本命令
  3. mysql 5.1 备份_mysql 5.1备份到5.0 USING BTREE
  4. Eclipse将整个项目的HTML文件编码改为UTF-8
  5. 注册中心—常见注册中心组件对比分析
  6. 5个构建Spring Boot API的实用技巧
  7. Studio 3T更改使用时间破解免费使用方式(转,可以使用)
  8. Git 入门 ---- Git 与 SVN 区别
  9. 1018 锤子剪刀布 (20 分)—PAT (Basic Level) Practice (中文)
  10. FPGA同步复位异步复位
  11. C# 压缩解压Zip文件
  12. ncbi-genome-download在NCBI上批量下载基因组
  13. /boot空间不足的解决办法
  14. 关键元器件选型设计指引--通用逻辑器件(逻辑IC)
  15. SpringBoot集成Swagger2、Swagger2和Swagger3的区别Swagger的注解学习
  16. 求最大公约数和最小公倍数
  17. 使用selenium自动登陆滴滴打码网
  18. 操作系统形式化验证实践教程(10) - 一阶直觉逻辑
  19. 高斯消元法线性方程组python_高斯消元法解线性方程组mpi并行
  20. 华为鸿蒙系统有驱鼠软件吗,华为还没正式发布鸿蒙系统,就开始提出苛刻条件,并非想用就能用...

热门文章

  1. 使用视频作为网页背景的技术探讨
  2. 梯度下降法、牛顿法和拟牛顿法——机器学习面试
  3. ubuntu不锁屏设置
  4. mysql关联查询 事务 索引 外键
  5. OpenShift-介绍
  6. 爬虫-演练-GET请求抓取网页的内容
  7. mysql进阶-02-事务的引入与基本的使用
  8. mysql-练习的数据准备
  9. linux-磁盘情况查询-待小结
  10. Vmware安装Centos7上网问题的解决