题干去内网找。。
开始读错题了,只要所有的操作都完成后与之前的无区别就好了。
这个反转用无旋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 long
using 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);
}