平衡树+并查集 string

来源:互联网 发布:云南卫生网络直报系统 编辑:程序博客网 时间:2024/06/07 12:16

题干去内网找。。
开始读错题了,只要所有的操作都完成后与之前的无区别就好了。
这个反转用无旋treap(splay都行)搞一下,dfs出最后的序列。
然后,初始序列和最终序列的同一位上为同一个字母。考虑两种情况
1.两个‘?’,用并查集搞进一个联通块即可。
2.一个字母,一个‘?’。那这个?所在联通块里所有?都得是那个字母。
把这里处理完了之后就是要去处理第k大。
只有剩下不多的联通块里的问号可以a~z随意取。而且只有联通块里最前面的一个?的取值决定着答案。
所以并查集时把最前面的?搞成父亲。统计出每个联通块第一个问号的顺序,然后搞一搞。具体怎么搞。。。某一个?要把字典序+1,那么总的排名变化,就是26^这个问号之后问号个数。稍微自己想想。。。不太好解释。通过这种方式能确定每一个?是哪个字母。。
然后输出即可。

#pragma GCC optimize("O3")#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define N 5*100005#define ll long longusing namespace std;int read(){    int sum=0,f=1;char x=getchar();    while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}    while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}    return sum*f;}int n,m,tot=26,cnt,a[N],b[N],f[N],vis[N],wz[N],hh[N];char s[N];ll xp[20],k;namespace Treap{    struct treap    {        treap* lc;treap* rc;        int sum,l,h,id;        treap(){lc=rc=NULL;id=rand();sum=l=h=0;}        inline void up(){sum=lc->sum+rc->sum+1;}    }*null=new treap(),*root=null,*zhan[N];    typedef pair<treap*,treap*> D;    void down(treap* &f)    {        if(f==null)return;        if(f->l)        {            f->l^=1;            if(f->lc!=null)f->lc->l^=1;            if(f->rc!=null)f->rc->l^=1;            swap(f->lc,f->rc);        }    }    D split(treap* f,int k)    {        if(f==null)return D(null,null);        D y;down(f);        if(f->lc->sum>=k){y=split(f->lc,k);f->lc=y.second;f->up();y.second=f;}        else{y=split(f->rc,k-f->lc->sum-1);f->rc=y.first;f->up();y.first=f;}        return y;    }    treap* merge(treap* a,treap* b)    {        if(a==null)return b;        if(b==null)return a;        down(a);down(b);        if(a->id<b->id){a->rc=merge(a->rc,b);a->up();return a;}        else {b->lc=merge(a,b->lc);b->up();return b;}    }    treap* newtreap(int k)    {        treap* o=new treap();        o->lc=o->rc=null;        o->sum=1;o->h=k;        return o;    }    void zhuan(int l,int r)    {        D y=split(root,l-1);        D x=split(y.second,r-l+1);        if(x.first!=null)x.first->l^=1;        root=merge(y.first,merge(x.first,x.second));    }    treap* build()    {        int x,p=0;treap *h,*las;        for(int i=1;i<=n;i++)        {            if(s[i]=='?')x=a[i]=++tot;            else a[i]=x=s[i]-'a';            h=newtreap(x);las=null;            while(p&&zhan[p]->id>h->id)            {                zhan[p]->up();las=zhan[p];zhan[p--]=null;            }            if(p)zhan[p]->rc=h;            h->lc=las;zhan[++p]=h;        }        while(p)zhan[p--]->up();        return zhan[1];    }    void dfs(treap* x)    {        if(x==null)return;        down(x);        if(x->lc!=null)dfs(x->lc);        b[++cnt]=x->h;        if(x->rc!=null)dfs(x->rc);    }}using namespace Treap;int find(int x){return f[x]==x?x:f[x]=find(f[x]);}int main(){    n=read();m=read();scanf("%lld",&k);    null->lc=null->rc=null;    scanf("%s",s+1);    root=build();    int l,r;    while(m--){l=read();r=read();zhuan(l,r);}    dfs(root);    for(int i=27;i<=tot;i++)f[i]=i;    for(int i=1;i<=n;i++)    {        if(b[i]>26)        {            if(a[i]>26)            {                int fx=find(b[i]),fy=find(a[i]);                if(fx^fy)                {                    if(fx<fy)f[fy]=fx;else f[fx]=fy;                    if(vis[fx])vis[fy]=1,hh[fy]=hh[fx];                    if(vis[fy])vis[fx]=1,hh[fx]=hh[fy];                }            }            else{int fx=find(b[i]);vis[fx]=1;hh[fx]=a[i];}        }        else            if(a[i]>26){int fx=find(a[i]);vis[fx]=1;hh[fx]=b[i];}    }    cnt=0;    for(int i=27;i<=tot;i++)    {        int fx=find(i);        if(vis[fx])continue;        if(fx==i){wz[++cnt]=fx;}    }    xp[0]=1;int i=1;    while(1)    {        xp[i]=xp[i-1]*26ll;        if(xp[i]>=k)break;        i++;    }    for(int j=1;j<=cnt-i;j++)hh[wz[j]]=0;    for(;i>0;i--)        for(ll j=1;j<=26;j++)            if(j*xp[i-1]>=k)            {                hh[wz[cnt-i+1]]=j-1;                k-=(j-1)*xp[i-1];                break;            }    for(int i=1;i<=n;i++)        if(b[i]>26)s[i]=hh[find(b[i])]+'a';        else s[i]=b[i]+'a';    printf("%s",s+1);}   
原创粉丝点击