平衡树+并查集 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);}
阅读全文
0 0
- 平衡树+并查集 string
- SGU 263 Tower(平衡树+并查集)
- bzoj 2733 [HNOI2012]永无乡 并查集+平衡树
- 【BZOJ】【P3545】【ONTAK2010】【Peaks】【题解】【离线+并查集+平衡树启发式合并】
- 【USACO 2008 Open Gold】 3.Cow Neighborhoods 平衡树、并查集
- 优先队列,二叉搜索树(非平衡),并查集
- Hdu 3726 Graph and Queries(并查集+平衡树+启发式合并)
- 【并查集+平衡树启发式合并】LibreOJ β Round #2[DP一般看规律]题解
- 树- 并查集
- hdu4641 K-string,后缀自动机,并查集
- hdu 4641 K-string(后缀自动机 + 并查集)
- Codeforces 828C String Reconstruction【思维+并查集】
- 并查集判断树
- 偶数树 并查集
- 10. 树--并查集
- 【bzoj4551】树 并查集
- HDU3938 并查集 并查集
- 并查集(集并查)
- Leetcode 680 Valid Palindrome II
- 国内计算机三大期刊+ JCST
- 实验二 线性表综合实验之双链表
- vue之登录路由验证
- shell脚本进行数据库查询(分库分表)
- 平衡树+并查集 string
- 自由幻想UI之切换成就列表
- stack usage
- 深度学习在目标跟踪中的应用
- 设计模式_1:简单工厂模式
- 计算机应用发展过程理论
- DataPicker和TimePicker
- Java 中带参带返回值方法的使用
- 芬伯格主张计算机设计重构计算机技术