CF1213F Unstable String Sort 题解

在毕克老师给的贪心题单中发现这道水紫,然后在AC后发现题解做法缤纷多彩,遂决定分享自己的做法。


思路

我们记 \(T\)\(S\) 排序后满足 \(\forall i\in[1,n-1],T[i]\le T[i+1]\) 的字符串,那么我们可以认为给出的排序 \(a\) , \(b\) 等价于给出了 \(T\) 中字符相同的位置。

即我们对于所有的 \(a_i=b_j=k\) 我们可以知道,\(T_{\min\{i,j\}\cdots\max\{i,j\}}\) 中的每个字符都是同一个 。

事实上我们可以得到 \(n\) 个类似于 \([\min\{i,j\},\max\{i,j\}]\) 的区间,表示区间内的字符都是同一个。

现在我们希望总的字符集合大小尽量大,因此我们只让有交的区间用同一个字符,即合并有交的区间。这一步可以按照左端点排序后贪心地维护。

维护后我们得到了一些两两不交的区间,同时由于 \(i\)\(j\) 都遍历 \(1\cdots n\) ,因此这些区间的并是 \([1,n]\) ,所以直接根据这些区间来构造方案是可行的,同时我们也可以根据这些区间的数量是否小于 \(k\) 来判断是否不能做到至少用 \(k\) 个字符。

只要按照区间从左到右的顺序依次赋值为 \(a,b,c\cdots\) ,如过超出 \(26\) 个全都赋值为 \(z\) ,这样我们就能构造出 \(T\) ,此时再根据给出的排列 \(a\) 或者 \(b\) 就可以得到 \(S\)

这样做显然是 \(\mathcal O(n\log n)\) 或者 \(\mathcal O(n)\)的,这取决于按照左端点排序时是用计数排序还是比较排序。

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#define MAXN 200000
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,j,k) for (int i=(j);i<=(k);++i) 
using namespace std;

struct seg{int l,r;}num[MAXN+5],ans[MAXN+5];
//seg表示区间
//ans是最终合并后的区间,num是一开始得到的区间
inline bool cmp(seg x,seg y) {return x.l<y.l;}
int a[MAXN+5],b[MAXN+5],ina[MAXN+5],inb[MAXN+5];
//a,b如题意,ina和inb分别表示值为i在a与b中的下标
int val[MAXN+5],cnt=-1;
//val是T中每个位置赋的值,cnt是合并后区间的个数
char ch[MAXN+5];
//ch是S

int main() {
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int n,k,l=0,r=0;
    cin>>n>>k;
    rep(i,1,n) cin>>a[i];
    rep(i,1,n) cin>>b[i];
    rep(i,1,n) ina[a[i]]=i;
    rep(i,1,n) inb[b[i]]=i;
    rep(i,1,n)
        num[i]=(seg){min(ina[i],inb[i]),max(ina[i],inb[i])};
    sort(num+1,num+n+1,cmp);
    rep(i,1,n) {
        if (num[i].l<=r) r=max(r,num[i].r);
        else {
            ans[++cnt]=(seg){l,r};
            l=num[i].l;r=num[i].r;
        }
    } 
    ans[++cnt]=(seg){l,r};
    if (cnt<k) {
        cout<<"NO\n";
        return 0;
    }
    cout<<"YES\n";
    rep(i,1,cnt)
        rep(j,ans[i].l,ans[i].r)
            val[j]=i;
    rep(i,1,n)
        ch[a[i]]='a'-1+min(26,val[i]);
    rep(i,1,n) cout<<ch[i];
    cout<<"\n";
    return 0;
} 

posted @ 2022-09-23 22:44  思考人生中…  阅读(35)  评论(0)    收藏  举报