CodeForces 1296 E2.String Coloring (hard version)

題意:

給定長度爲n的字符串
現在要給字符串的每個字符塗色,塗完色之後:
如果相鄰位置的字符顏色不一樣,則可以交換他們的位置
現在要你構造出一種塗色方案,使得能夠通過交換讓最後字符串字典序最小,且塗色所需不同顏色數量最少

思路:

字典序最小即數組非嚴格遞增(非遞減)
因爲只有相鄰位置顏色不一樣才能交換,可以發現塗完色之後,相同顏色的字符的相對位置是不發生變化的。
又因爲需要非嚴格遞增,所以相同顏色的必須非嚴格遞增。
從左到右遍歷字符串,對於第一個字符a1,顏色爲1。對於第二個字符a2,如果a2大於等於a1,那麼也爲1,如果a2小於a1,因爲相同顏色必須非嚴格遞增,因此a2的顏色不能和a1相同,塗色爲2。對於第三個字符a3,如果a3最大,那麼塗色爲2,否則計算前面比a3大的字符的顏色最大值,假設爲ma,則a3至少塗色爲ma+1,a3的顏色爲(ma+1)與(和a3相等的字符顏色)中的最大值。
另外就是可以開一個大小爲26的數組維護每種字符的顏色最大值,便於查找。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxm=2e5+5;
char s[maxm];
int ans[maxm];
int d[33];//每種字符的顏色最大值
signed main(){
    int n;
    cin>>n;
    scanf("%s",s+1);
    int cnt=0;
    for(int i=1;i<=n;i++){
        int ma=0;
        for(int j=s[i]-'a'+1;j<26;j++){//前面比他大的字符的最大顏色
            ma=max(ma,d[j]);
        }
        d[s[i]-'a']=max(d[s[i]-'a'],ma+1);//更新最大顏色
        ans[i]=max(d[s[i]-'a'],ma+1);//當前位置顏色
        cnt=max(ans[i],cnt);//更新顏色數量
    }
    cout<<cnt<<endl;
    for(int i=1;i<=n;i++){
        cout<<ans[i]<<' ';
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章