【NOIP2017】列队
题面
https://www.luogu.org/problem/P3960
题解
搬运一下去年的工作。
题解是$splay$,但是我傻逼写的$treap$。
对于$n=1$的情况,$treap$维护序列插入删除,对于$n$任意的情况,动态开点就可以了。
#include<cstdio> #include<iostream> #include<cstring> #include<ctime> #include<cstdlib> using namespace std; const long long INF=1e8; const double eqs=1e-6; struct node{ node *ch[2],*fa; long long pri,s,l,siz; long long val; } root[300500],r; long long n,m,q,x,y,mv[300500],mrv,rank,rk2; bool opt(node *x) { return (x->fa->ch[1]==x); } void rotate(node *x) { node *y=x->fa; bool o=opt(x); x->fa=y->fa; y->fa->ch[opt(y)]=x; y->fa=x; y->ch[o]=x->ch[1^o]; if (x->ch[1^o]!=NULL) x->ch[1^o]->fa=y; x->ch[1^o]=y; y->siz=y->l; if (y->ch[0]!=NULL) y->siz+=y->ch[0]->siz; if (y->ch[1]!=NULL) y->siz+=y->ch[1]->siz; x->siz=x->l + y->siz; if (x->ch[o]!=NULL) x->siz+=x->ch[o]->siz; } void insert(node *now,long long v,long long s,long long l) { now->siz+=l; if (now->ch[v>now->val]==NULL) { node *xx=new node; now->ch[v>now->val]=xx; xx->val=v, xx->pri=rand()%INF, xx->s=s, xx->l=l , xx->siz=l , xx->fa=now; while (xx->pri > xx->fa->pri) rotate(xx); return; } else insert(now->ch[v>now->val],v,s,l); } void erase(node *now) { int le=now->l; now->l=0; node *it=now; while (it!=NULL) it->siz-=le,it=it->fa; int cnt; while (true) { cnt=0; if (now->ch[0]!=NULL) cnt++; if (now->ch[1]!=NULL) cnt++; if (cnt==0) { now->fa->ch[opt(now)]=NULL; //while (now!=NULL) now->siz-=len,now=now->fa; return; } else if (cnt==1) { if (now->ch[0]!=NULL) cnt=0; else cnt=1; now->fa->ch[opt(now)]=now->ch[cnt]; now->ch[cnt]->fa=now->fa; //while (now!=NULL) now->siz-=len,now=now->fa; return; } else { if (now->ch[0]->pri > now->ch[1]->pri) cnt=0; else cnt=1; rotate(now->ch[cnt]); } } } long long fbrdd(node *now) { if (now==NULL) return -1; long long les; if (now->ch[0]!=NULL) les=now->ch[0]->siz; else les=0; if (rk2+les == x) { erase(now); return now->s; } else if (x<rk2+les) return fbrdd(now->ch[0]); else { rk2+=les+1; return fbrdd(now->ch[1]); } } void del(node *now,long long mi){ //printf("ylq %lld\n",mi); int le=now->l; now->l=0; node *it=now; while (it!=NULL) it->siz-=le,it=it->fa; int cnt; bool suc=false; now->val=-1; while (true) { //printf("DEBUG shx %lld\n",mi); cnt=0; if (now->ch[0]!=NULL) cnt++; if (now->ch[1]!=NULL) cnt++; if (cnt==0 && !suc) { suc=true; if (mi-now->s) { //printf("DEBUG %lld %lld %lld\n",now->s,le,mi); node *ch0=new(node); ch0->ch[0]=NULL, ch0->ch[1]=NULL, ch0->fa=now, ch0->pri=rand()%INF, ch0->s=now->s, ch0->l=mi-now->s, ch0->siz=mi-now->s; ch0->val=now->val; now->ch[0]=ch0; int len=ch0->siz; it=ch0; while (it->fa!=NULL) it=it->fa,it->siz+=len; while (ch0->pri > ch0->fa->pri) rotate(ch0); } if (now->s+le-1-mi) { //printf("DEBUG %lld %lld %lld\n",now->s,le,mi); node *ch1=new(node); ch1->ch[0]=NULL, ch1->ch[1]=NULL, ch1->fa=now, ch1->pri=rand()%INF, ch1->s=mi+1, ch1->l=now->s+le-1-mi, ch1->siz=now->s+le-1-mi; ch1->val=now->val; now->ch[1]=ch1; int len=ch1->siz; it=ch1; while (it->fa!=NULL) it=it->fa,it->siz+=len; while (ch1->pri > ch1->fa->pri) rotate(ch1); } } else if (cnt==0 && suc) { now->fa->ch[opt(now)]=NULL; return; } else if (cnt==1 && !suc) { if (now->ch[0]!=NULL) cnt=0; else cnt=1; rotate(now->ch[cnt]); } else if (cnt==1 && suc) { if (now->ch[0]!=NULL) cnt=0; else cnt=1; now->fa->ch[opt(now)]=now->ch[cnt]; now->ch[cnt]->fa=now->fa; return; } else { if (now->ch[0]->pri > now->ch[1]->pri) cnt=0; else cnt=1; rotate(now->ch[cnt]); } } } void fbrd(node *now) { if (now==NULL) return; long long les; if (now->ch[0]!=NULL) les=now->ch[0]->siz; else les=0; if (rank+les <= y && y < rank+les+now->l) { long long mid=now->s+(y-rank-les); printf("%lld\n",mid); del(now,mid); long long nxt=fbrdd(&r); insert(&root[x],++mv[x],nxt,1); insert(&r,++mrv,mid,1); } else if (y<rank+les) fbrd(now->ch[0]); else rank+=les+now->l,fbrd(now->ch[1]); } void dfs(node *now){ if (now->ch[0]!=NULL) dfs(now->ch[0]); printf("DEBUG : %lld %lld\n",now->s,now->l); if (now->ch[1]!=NULL) dfs(now->ch[1]); } int main(){ long long i; scanf("%lld %lld %lld",&n,&m,&q); r.val=-INF,r.pri=INF,r.s=-1,r.siz=1,r.l=1; mrv=0; for (i=1;i<=n;i++) { root[i].val=-INF,root[i].pri=INF,root[i].s=-1,root[i].siz=1,root[i].l=1; insert(&root[i],++mv[i],(i-1)*m+1,m-1); insert(&r,++mrv,i*m,1); } for (i=1;i<=q;i++) { rank=rk2=0; scanf("%lld %lld",&x,&y); //dfs(&root[x]); if (y==m) { long long nxt=fbrdd(&r); printf("%lld\n",nxt); insert(&r,++mrv,nxt,1); } else fbrd(&root[x]); } return 0; }