标签:split kth span merge 平衡 uil 16px main amp
虽然放在第三题但是其实这题没有什么思维难度,就是建$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);
}
}
}
标签:split kth span merge 平衡 uil 16px main amp
原文地址:http://www.cnblogs.com/jefflyy/p/7845444.html