Codeforces Round #617 (Div. 3) --- E2

通過做這道題學到了很多知識,還是很好的,用到Dilworth定理

題目傳送門

Dilworth定理

解題思路:

  • 就是給你一堆字母,ababcdba,最終讓你排成aaabbbcd(字典序最小)
  • 如果2個位置的字母塗的顏色不同,那麼他們可以交換,問的是用最少的顏色進行塗色,我們最少需要多少種顏色, 而且將他們的位置的顏色標記出來。
  • 這裏用到Dilworth定理:不上升子序列的數目 == 最長下降子序列的長度 (反之亦然,如果想看正面的點上面的鏈接即可)
  • 這個題簡單的來說是找有多少個不下降子序列,也就是能劃分多少個全序集(可以自己推一下,因爲如果是不下降的他們的顏色也不會變,所以找全序集的個數)
  • 然後就推理出找最長下降子序列的長度,但是這個題不同於導彈攔截(洛谷的,可以去查下),他還需要整上顏色。
  • 那麼我們可以將當前位置字母的顏色變爲比他大一的字母的顏色+1,比如d c b a 這四個字母吧,他們的顏色分別是1,2,3,4 因爲都要進行交換,所以我們讓當前字母的顏色爲上一個顏色 + 1。
  • 然後我們要讓小於等於這個字母的顏色都爲當前的最大值(從小到大塗),例如 c a 吧,a的大一個的爲b,但是b是0,所以a塗1,但是c也是塗成1的,所以顯然是不對的所以我們將<= c 的字符的顏色都塗成當前的最大的(可以看代碼理解下)
  • 最終輸出即可

代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 200010;

int a[N];
int ans[N];

int main(){
    int n;
    scanf("%d",&n);
    string st;
    cin>>st;
    int res = 0;
    for (int i = 0; i < n; i++){
        ans[i] = a[st[i] - 'a' + 1] + 1;
        res = max(ans[i],res);
        a[st[i]-'a'] = ans[i];
        int mx = 0;
        for (int j = 26; j >= 0; j--){
            a[j] = max(mx,a[j]);
            mx = a[j];
        } 
    }
    printf("%d\n",res);
    for (int i = 0; i < n; i++){
        printf("%d ",ans[i]);
    }
    puts("");
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章