Codeforces Round #617 (Div. 3) String Coloring(E1.E2)

(easy version):node

題目連接:http://codeforces.com/contest/1296/problem/E1ios

 

題目一句話就是說,兩種顏色不一樣的字符能夠相互換位,spa

問,對這字符串用最多兩種顏色染色,而後通過有限次換位code

能夠變成字典序排序的順序。blog

 

思路:一個字符需不須要換位,應該是參照最後的字典序的順序,排序

那麼,咱們應該給字符串排序,再去思考問題。ci

咱們知道,若是str[now_i]的位置和排序後的位置不同,那就是須要換位。字符串

咱們還知道,若是str[now_i]的當前位置若是小於等於排序後的位置,get

說明str[now_i]會日後移動,以前應該是會多出(>=0)個字符,那麼咱們不妨string

讓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 }
相關文章
相關標籤/搜索