bzoj 3678 wangxz与OJ
3678: wangxz与OJ
Time Limit: 10 Sec Memory Limit: 128 MBhttp://www.lydsy.com/JudgeOnline/problem.php?id=3678
Description
某天,wangxz神犇来到了一个信息学在线评测系统(Online Judge)。由于他是一位哲♂学的神犇,所以他不打算做题。他发现这些题
目呈线性排列,被标记为1~n号,每道题都有一个难度值(可以<=0)。他决定与这些题目玩♂耍。
1、他可以在某个位置插♂入一些难度值特定的题目。
2、他可以吃♂掉(删除)一段题目。
3、他可以查询某个位置的题目的难度值。
维护一个初始有n个元素的序列(标记为1~n号元素),支持以下操作:
0 p a b (0<=p<=当前序列元素个数) (a<=b) 在p位置和p+1位置之间插入整数:a,a+1,a+2,...,b-1,b。若p为0,插在序列最前面;
1 a b (1<=a<=b<=当前序列元素个数) 删除a,a+1,a+2,...,b-1,b位置的元素;
2 p (1<=p<=当前序列元素个数) 查询p位置的元素。
Input
输入第一行包括两个正整数n(1<=n<=20000),m(1<=m<=20000),代表初始序列元素个数和操作个数。
接下来n个整数,为初始序列元素。
接下来m行,每行第一个为整数sym,
若sym=0,接下来有一个非负整数p,两个整数a,b;
若sym=1,接下来有两个正整数a,b;
若sym=2,接下来有一个正整数p;
p、x、y的含义及范围见题目描述。
在任何情况下,保证序列中的元素总数不超过100000。
保证题目涉及的所有数在int内。
Output
对每个sym=2,输出一行,包括一个整数,代表询问位置的元素。
Sample Input
5 3
1 2 3 4 5
0 2 1 4
1 3 8
2 2
1 2 3 4 5
0 2 1 4
1 3 8
2 2
Sample Output
2
插入时插一个大节点,使用到他时分裂节点
大节点发现是公差为1的等差数列,所以记录首项、末项即可
#include<cstdio> #define N 20001 using namespace std; int n,m,tot,t1,t2,root; int key[N*10][2],siz[N*10],ch[N*10][2],fa[N*10]; int read() { int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } struct SPLAY_TREE { void update(int k) { siz[k]=key[k][1]-key[k][0]+1; if(ch[k][0]) siz[k]+=siz[ch[k][0]]; if(ch[k][1]) siz[k]+=siz[ch[k][1]]; } void build(int l,int r,int f) { if(l>r) return; int mid=l+r>>1; siz[mid]=1; fa[mid]=f; ch[f][mid>f]=mid; build(l,mid-1,mid); build(mid+1,r,mid); update(mid); } void rotate(int x,int & goal) { int y=fa[x],z=fa[y],k=ch[y][1]==x; if(y==goal) goal=x; else ch[z][ch[z][1]==y]=x; ch[y][k]=ch[x][k^1]; ch[x][k^1]=y; fa[y]=x; fa[ch[y][k]]=y; fa[x]=z; update(y); } bool getson(int x) { return ch[fa[x]][1]==x; } void splay(int x,int & goal) { while(x!=goal) { int y=fa[x]; if(y!=goal) { if(getson(x)==getson(y)) rotate(y,goal); else rotate(x,goal); } rotate(x,goal); update(x); } } int find(int now,int k) { if(k<=siz[ch[now][0]]) return find(ch[now][0],k); else if(siz[now]-siz[ch[now][1]]<k) return find(ch[now][1],k-siz[now]+siz[ch[now][1]]); else { k-=siz[ch[now][0]]; if(k!=1) { fa[ch[++tot][0]=ch[now][0]]=tot; fa[ch[now][0]=tot]=now; key[tot][0]=key[now][0]; key[tot][1]=key[tot][0]+k-2; key[now][0]=key[tot][1]+1; update(tot); k=1; } if(k!=key[now][1]-key[now][0]+1) { fa[ch[++tot][1]=ch[now][1]]=tot; fa[ch[now][1]=tot]=now; key[tot][1]=key[now][1]; key[tot][0]=key[now][0]+k; key[now][1]=key[tot][0]-1; update(tot); } return now; } } void spilt(int l,int r) { t1=find(root,l); t2=find(root,r); splay(t1,root); splay(t2,ch[root][1]); } }Splay; int main() { /*freopen("data.txt","r",stdin); freopen("my2.txt","w",stdout);*/ n=read(); m=read(); for(int i=1;i<=n;i++) key[i+1][0]=key[i+1][1]=read(); Splay.build(1,n+2,0); tot=n+2; root=n+3>>1; int op,p,a,b; while(m--) { scanf("%d",&op); if(!op) { p=read(); a=read(); b=read(); Splay.spilt(p+1,p+2); fa[ch[t2][0]=++tot]=t2; key[tot][0]=a; key[tot][1]=b; siz[tot]=b-a+1; Splay.update(t2); Splay.update(t1); } else if(op==1) { a=read(); b=read(); Splay.spilt(a,b+2); ch[t2][0]=0; Splay.update(t2); Splay.update(t1); } else { p=read(); p=Splay.find(root,p+1); printf("%d\n",key[p][0]); } } }
狂WA代码:
#include<cstdio> #define N 20005 using namespace std; int n,m,now,tmp,root; int a[N]; int siz[N*200],fa[N*200],key[N*200],ch[N*200][2],cnt[N*200]; int tot; struct SPLAY_TREE { void update(int k) { siz[k]=cnt[k]; if(ch[k][0]) siz[k]+=siz[ch[k][0]]; if(ch[k][1]) siz[k]+=siz[ch[k][1]]; } void build(int l,int r,int f) { if(l>r) return; int mid=l+r>>1; if(mid<f) ch[f][0]=mid; else ch[f][1]=mid; siz[mid]=1; cnt[mid]=1; fa[mid]=f; key[mid]=a[mid]; build(l,mid-1,mid); build(mid+1,r,mid); update(mid); } int find_id(int x) { now=root; while(1) { if(ch[now][0]&&siz[ch[now][0]]>=x) now=ch[now][0]; else { tmp=(ch[now][0] ? siz[ch[now][0]] : 0)+cnt[now]; if(x<=tmp) return now; x-=tmp; now=ch[now][1]; } } } int getson(int x) { return ch[fa[x]][0]==x; } void rotate(int x,int & goal) { int y=fa[x],z=fa[y],k=ch[y][1]==x; if(y==goal) goal=x; else ch[z][ch[z][1]==y]=x; ch[y][k]=ch[x][k^1]; ch[x][k^1]=y; fa[y]=x; fa[ch[y][k]]=y; fa[x]=z; update(y); } void splay(int x,int & goal) { int y; while(x!=goal) { y=fa[x]; if(y!=goal) { if(getson(x)==getson(y)) rotate(y,goal); else rotate(x,goal); } rotate(x,goal); update(x); } } void insert_suf(int s,int t) { if(!ch[root][1]) now=root; else { now=ch[root][1]; while(ch[now][0]) now=ch[now][0]; } siz[++tot]=cnt[tot]=t-s+1; key[tot]=(s+t)*(t-s+1)/2; fa[tot]=now; ch[now][0]=tot; splay(tot,root); } void insert_pre(int s,int t) { if(!ch[root][0]) now=root; else { now=ch[root][0]; while(ch[now][1]) now=ch[now][1]; } siz[++tot]=cnt[tot]=t-s+1; key[tot]=(s+t)*(t-s+1)/2; fa[tot]=now; ch[now][1]=tot; splay(tot,root); } int find_pre() { now=ch[root][0]; while(ch[now][1]) now=ch[now][1]; return now; } int find_suf() { now=ch[now][1]; while(ch[now][0]) now=ch[now][0]; return now; } void del() { if(!ch[root][0]&&!ch[root][1]) root=0; else if(!ch[root][0]) { tmp=root; root=ch[root][1]; fa[root]=0; ch[tmp][1]=0; } else if(!ch[root][1]) { tmp=root; root=ch[root][0]; fa[root]=0; ch[tmp][0]=0; } else { int pre=find_pre(); tmp=root; splay(pre,root); ch[root][1]=ch[tmp][1]; if(ch[root][1]) fa[ch[root][1]]=root; update(root); } } }Splay; int main() { /*freopen("data.txt","r",stdin); freopen("my.txt","w",stdout);*/ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i+1]); Splay.build(1,n+2,0); root=n+3>>1; int op,p,aa,bb,q; int cutl,cutr; int shouxiang1,shouxiang2,moxiang1,moxiang2,rest_in_aa,rest_in_bb; tot=n+3; while(m--) { scanf("%d",&op); if(op==0) { scanf("%d%d%d",&p,&aa,&bb); p++;q=p; p=Splay.find_id(p); Splay.splay(p,root); if(cnt[p]==1) Splay.insert_suf(aa,bb); else { cutl=q-siz[ch[root][0]]-1; cutr=siz[root]-siz[ch[root][1]]-q; shouxiang1=(2*key[root]/cnt[root]-cnt[root]+1)/2; moxiang1=shouxiang1+cutl-1; shouxiang2=moxiang1+2; moxiang2=shouxiang2+cutr-1; siz[root]=siz[root]-cnt[root]+1; cnt[root]=1; key[root]=moxiang1+1; Splay.insert_pre(shouxiang1,moxiang1); Splay.splay(p,root); Splay.insert_suf(shouxiang2,moxiang2); Splay.splay(p,root); Splay.insert_suf(aa,bb); } } else if(op==1) { scanf("%d%d",&aa,&bb); aa++; bb++; p=aa; q=bb; aa=Splay.find_id(aa); bb=Splay.find_id(bb); if(aa==bb) { Splay.splay(aa,root); cutl=p-siz[ch[root][0]]-1; //cutr=siz[root]-siz[ch[root][1]]-q; cutr=cnt[root]-cutl-(q-p+1); shouxiang1=(2*key[root]/cnt[root]-cnt[root]+1)/2; moxiang1=shouxiang1+cutl-1; shouxiang2=moxiang1+q-p+2;//+1 moxiang2=shouxiang2+cutr-1; if(shouxiang1<=moxiang1) { Splay.insert_pre(shouxiang1,moxiang1);//++ Splay.splay(aa,root); siz[root]=siz[root]-(moxiang1-shouxiang1+1); cnt[root]=cnt[root]-(moxiang1-shouxiang1+1); key[root]=key[root]-(shouxiang1+moxiang1)*(moxiang1-shouxiang1+1)/2; } siz[root]=siz[root]-(q-p+1); cnt[root]=cnt[root]-(q-p+1); key[root]=key[root]-(shouxiang2-1+shouxiang2-1-(q-p+1)+1)*(q-p+1)/2; if(!cnt[root]) Splay.del(); continue; } Splay.splay(aa,root); rest_in_aa=p-siz[ch[root][0]]-1; Splay.splay(bb,ch[root][1]); rest_in_bb=cnt[bb]-(q-p+1-(cnt[aa]-rest_in_aa+siz[ch[bb][0]]));//+1 siz[aa]-=siz[ch[bb][0]]; siz[bb]-=siz[ch[bb][0]]; ch[bb][0]=0; shouxiang1=(2*key[bb]/cnt[bb]-cnt[bb]+1)/2; key[bb]-=(shouxiang1+shouxiang1+cnt[bb]-rest_in_bb-1)*(cnt[bb]-rest_in_bb)/2; cnt[bb]=rest_in_bb; Splay.update(bb); shouxiang1=(2*key[aa]/cnt[aa]-cnt[aa]+1)/2; key[aa]=(shouxiang1+shouxiang1+rest_in_aa-1)*rest_in_aa/2; cnt[aa]=rest_in_aa; Splay.update(aa); } else { scanf("%d",&p); p++; q=Splay.find_id(p); if(cnt[q]==1) printf("%d\n",key[q]); else { Splay.splay(q,root); p=p-siz[ch[root][0]]; shouxiang1=(2*key[root]/cnt[root]-cnt[root]+1)/2; printf("%d\n",shouxiang1+p-1); } } } }