zoukankan      html  css  js  c++  java
  • Codeforces Round #617 (Div. 3) String Coloring(E1.E2)

    (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
    ";
    50     else{
    51         cout << "YES
    ";
    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 }
  • 相关阅读:
    使用window.postMessage实现跨域通信
    关于angularJS绑定数据时自动转义html标签
    细小知识点
    理解Java多态
    Java自定义类加载器与双亲委派模型详解
    python之5种数据类型7种运算符
    Innodb中的事务隔离级别实现原理
    Redis分布式锁
    leetcode series:Two Sum
    设计模式六大原则(转)
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/12283772.html
Copyright © 2011-2022 走看看