虽然放在第三题但是其实这题没有什么思维难度,就是建$n$棵区间节点平衡树维护每行的前$m-1$个数,再建一棵平衡树维护最后一列
我用了splay,维护移动操作的确是挺简单的
但考前没有写过这种点代表区间而且要动态开点的题,怕写错不敢写,只写了60分
但实际上还是得敢写,既然自己肝了那么久splay确保自己不会写错那么为什么不试试新东西呢
其实也不是太困难,要找$x$,如果当前区间为$[l,r]$且$l\leq x\leq r$就把区间分成$[l,x-1],x,[x+1,r]$三部分就行了,没有太多细节
割分与合并记得更新父节点的信息就好
#include<stdio.h> #define ll long long struct node{ ll l,r; int siz,fa,ch[2]; }t[1200010]; int root[300010],tot,n,m; void pushup(int x){ t[x].siz=t[t[x].ch[0]].siz+t[t[x].ch[1]].siz+(int)(t[x].r-t[x].l+1); } void rot(int x){ int y,z,B,f; y=t[x].fa; z=t[y].fa; f=(t[y].ch[0]==x); B=t[x].ch[f]; t[x].fa=z; t[y].fa=x; if(B)t[B].fa=y; t[x].ch[f]=y; t[y].ch[f^1]=B; if(t[z].ch[0]==y)t[z].ch[0]=x; if(t[z].ch[1]==y)t[z].ch[1]=x; pushup(y); pushup(x); } void splay(int x){ int y,z; while(t[x].fa){ y=t[x].fa; z=t[y].fa; if(z)rot((t[z].ch[0]==y&&t[y].ch[0]==x)||(t[z].ch[1]==y&&t[y].ch[1]==x)?y:x); rot(x); } } int getkth(int x,int k){ if(t[t[x].ch[0]].siz<k&&k<=t[x].siz-t[t[x].ch[1]].siz){ ll p=t[x].l+(ll)(k-t[t[x].ch[0]].siz-1); if(t[x].l<p){ tot++; t[tot].l=t[x].l; t[tot].r=p-1; t[tot].fa=x; t[tot].ch[0]=t[x].ch[0]; t[t[x].ch[0]].fa=tot; t[x].ch[0]=tot; t[x].l=p; pushup(tot); } if(p<t[x].r){ tot++; t[tot].l=p+1; t[tot].r=t[x].r; t[tot].fa=x; t[tot].ch[1]=t[x].ch[1]; t[t[x].ch[1]].fa=tot; t[x].ch[1]=tot; t[x].r=p; pushup(tot); } pushup(x); return x; } int f; if(k<=t[t[x].ch[0]].siz)f=getkth(t[x].ch[0],k); if(k>t[x].siz-t[t[x].ch[1]].siz)f=getkth(t[x].ch[1],k-t[x].siz+t[t[x].ch[1]].siz); pushup(x); return f; } void build(int l,int r,int&x){ if(x==0){ tot++; x=tot; } int mid=(l+r)>>1; t[x].l=t[x].r=m*(ll)mid; if(l<mid){ build(l,mid-1,t[x].ch[0]); t[t[x].ch[0]].fa=x; } if(mid<r){ build(mid+1,r,t[x].ch[1]); t[t[x].ch[1]].fa=x; } pushup(x); } int merge(int x,int y){ if(x==0||y==0)return x|y; while(t[x].ch[1])x=t[x].ch[1]; splay(x); t[x].ch[1]=y; t[y].fa=x; pushup(x); return x; } int split(int p){ int k,j; k=t[p].ch[0]; j=t[p].ch[1]; t[p].ch[0]=t[p].ch[1]=0; t[k].fa=t[j].fa=0; pushup(p); return merge(k,j); } int main(){ freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); int q,i,x,y,p,f; scanf("%d%d%d",&n,&m,&q); if(m>1){ for(i=1;i<=n;i++){ root[i]=i; t[i].l=m*(ll)(i-1)+1ll; t[i].r=m*(ll)(i-1)+(ll)(m-1); t[i].siz=m-1; } tot=n; } build(1,n,root[n+1]); while(q--){ scanf("%d%d",&x,&y); if(y==m){ p=getkth(root[n+1],x); splay(p); printf("%lld\n",t[p].l); root[n+1]=split(p); root[n+1]=merge(root[n+1],p); }else{ p=getkth(root[x],y); splay(p); printf("%lld\n",t[p].l); f=getkth(root[n+1],x); splay(f); root[x]=split(p); root[n+1]=split(f); root[x]=merge(root[x],f); root[n+1]=merge(root[n+1],p); } } }
时间: 2024-11-09 13:49:20