BZOJ3678 wangxz与OJ
由于题面包含不良信息,因此这里只放传送门。
题目大意:
维护一个序列,支持:
1、区间删除
2、在一个位置插入一段递增或递减的连续的数
3、单点查询
$splay$拆点,一个节点表示段连续的区间,必要时将一个点分裂成两个点。
空间一定是线性的,思维含量并不高,但是细节一堆。
很裸吧......
你写吧......
我们强无敌的$wxjor$巨佬以$6KB$代码$47pt$收场。
俗话说得好
有些人还活着,但它们的代码已经调不出来了。
有些人已经死了,但它们的代码还没有调出来。
只要写不死,就往死里写。
$Orz$模拟赛里$Ac$的神爷们
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define M 600020 #define ls c[x][0] #define rs c[x][1] using namespace std; int read(){ int nm=0,fh=1; char cw=getchar(); for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh; for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0'); return nm*fh; } int tpe,n,m,T,c[M][2],cnt,rt,fa[M],L[M],R[M],sum[M],X,Y; void pushup(int x){sum[x]=sum[ls]+sum[rs]+abs(R[x]-L[x])+1;} void rotate(int x){ int tp=fa[x],dtp=fa[fa[x]],ms,ds; if(dtp&&c[dtp][0]==tp) c[dtp][0]=x; else if(dtp) c[dtp][1]=x; if(c[tp][0]==x) ms=0,ds=1;else ds=0,ms=1; fa[x]=dtp,fa[tp]=x,fa[c[x][ds]]=tp; c[tp][ms]=c[x][ds],c[x][ds]=tp,pushup(tp),pushup(x); } void splay(int x,int tar){ while(fa[x]!=tar){ int tp=fa[x]; if(fa[tp]==tar){rotate(x);break;} if(c[c[fa[tp]][0]][0]==x) rotate(tp); else if(c[c[fa[tp]][1]][1]==x) rotate(tp); else rotate(x); } if(!tar) rt=x; } int fd(int x,int rk){ if(sum[ls]>=rk) return fd(ls,rk); if(sum[x]-sum[rs]>=rk) return x; return fd(rs,rk-sum[x]+sum[rs]); } int mn(int x){for(;ls;x=ls); return x;} int query(int pos){ int x=fd(rt,pos),dt,rm; splay(x,0); dt=(R[x]>=L[x]?1:-1),rm=pos-sum[ls]-1; return L[x]+rm*dt; } void ins(int pos,int t1,int t2){ int x=++cnt,u; L[x]=t1,R[x]=t2,pushup(x); if(!rt){rt=x; return;} if(!pos){rs=rt,fa[rt]=x,rt=x,pushup(x);return;} int now=fd(rt,pos); splay(now,0); if(sum[now]-sum[c[now][1]]==pos){ if((u=mn(c[now][1]))==0) c[now][1]=x,fa[x]=now,pushup(now); else splay(u,now),c[u][0]=x,fa[x]=u,pushup(u),pushup(now); } else{ int dt=(R[now]>=L[now]?1:-1),rm=pos-sum[c[now][0]]; cnt++,R[cnt]=R[now],L[cnt]=dt*rm+L[now],R[now]=L[cnt]-dt; c[cnt][1]=c[now][1],c[now][1]=0,pushup(now),pushup(cnt),fa[c[cnt][1]]=cnt; ls=now,rs=cnt,fa[now]=fa[cnt]=x,rt=x,fa[0]=0,pushup(x); } } void del(int t1,int t2){ int x=fd(rt,t1),y=fd(rt,t2),u,dt; splay(x,0); t1-=sum[ls],splay(y,0),t2-=sum[c[y][0]]; if(x!=y){ splay(x,y),rs=0,pushup(x),pushup(y); if(t1>1) dt=(R[x]>=L[x]?1:-1),R[x]=L[x]+dt*(t1-2),pushup(x),pushup(y); else fa[ls]=y,fa[0]=0,c[y][0]=ls,pushup(y); x=y; if(t2<abs(R[x]-L[x])+1) dt=(R[x]>=L[x]?1:-1),L[x]+=dt*t2,pushup(x); else if((y=mn(rs))==0) rt=ls,fa[ls]=0; else splay(y,x),rt=y,c[y][0]=ls,fa[ls]=y,fa[y]=0,pushup(y); } else{ dt=(R[x]>=L[x]?1:-1); if(t2-t1==abs(R[x]-L[x])){ if((u=mn(rs))==0) rt=ls,fa[ls]=0; else splay(u,x),c[u][0]=ls,fa[ls]=u,fa[u]=0,rt=u,pushup(u); } else if(t1==1) L[x]+=(t2-t1+1)*dt,pushup(x); else if(t2==abs(R[x]-L[x])+1) R[x]-=(t2-t1+1)*dt,pushup(x); else{ if((u=mn(rs))==0) rs=++cnt,fa[cnt]=x; else splay(u,x),c[u][0]=++cnt,fa[cnt]=u; R[cnt]=R[x],R[x]=L[x]+(t1-2)*dt,L[cnt]=R[x]+(t2-t1+2)*dt; pushup(cnt),pushup(rs),sum[x]=0,pushup(x); } } } int main(){ n=read(),T=read(); for(int i=1;i<=n;i++) m=read(),ins(i-1,m,m); while(T--){ tpe=read(),X=read(); if(tpe==2) printf("%d\n",query(X)); else if(tpe==1) Y=read(),del(X,Y); else tpe=X, X=read(),Y=read(),ins(tpe,X,Y); } return 0; }