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;
}


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