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
HINT
Source
splay题,用到了动态开点

#include<bits/stdc++.h>
using namespace std;
struct tree{
int len,size,num,ch[2],fa;
}t[120005];
int root,tot,n,m;
void pushup(int x){
t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].len;
}
int chk(int x){
return t[t[x].fa].ch[1]==x;
}
void rotate(int x){
int y=t[x].fa,z=t[y].fa,k=chk(x),w=t[x].ch[k^1];
t[y].ch[k]=w;
t[w].fa=y;
t[z].ch[chk(y)]=x;
t[x].fa=z;
t[x].ch[k^1]=y;
t[y].fa=x;
pushup(y);
pushup(x);
}
void splay(int x,int goal=0){
while(t[x].fa!=goal){
int y=t[x].fa,z=t[y].fa;
if(z!=goal) if(chk(x)==chk(y)) rotate(y);
else rotate(x);
rotate(x);
}
if(!goal) root=x;
}
int kth(int k){
int cur=root;
while(1){
if(t[t[cur].ch[0]].size>=k) cur=t[cur].ch[0];
else if(t[t[cur].ch[0]].size+t[cur].len<k) k-=t[t[cur].ch[0]].size+t[cur].len,cur=t[cur].ch[1];
else {
k-=t[t[cur].ch[0]].size;
if(k!=1){
t[++tot].fa=cur;
t[tot].ch[0]=t[cur].ch[0];
t[tot].num=t[cur].num;
t[t[cur].ch[0]].fa=tot;
t[tot].len=k-1;
t[cur].ch[0]=tot;
pushup(tot);
}
if(k!=t[cur].len){
t[++tot].fa=cur;
t[tot].ch[0]=t[cur].ch[1];
t[tot].num=t[cur].num+k;
t[t[cur].ch[1]].fa=tot;
t[tot].len=t[cur].len-k;
t[cur].ch[1]=tot;
pushup(tot);
}
t[cur].len=1;t[cur].num+=k-1;
return cur;
}
}
}
int build(int l,int r){
int mid=(l+r)>>1;
if(l!=mid) t[mid].ch[0]=build(l,mid-1),t[t[mid].ch[0]].fa=mid;
if(mid!=r) t[mid].ch[1]=build(mid+1,r),t[t[mid].ch[1]].fa=mid;
pushup(mid);
return mid;
}
int split(int l,int r){
l=kth(l);r=kth(r+2);
splay(l);
splay(r,l);
return r;
}
int main(){
scanf("%d%d",&n,&m);
t[1].size=t[1].len=1;
for(int i=1;i<=n;i++) scanf("%d",&t[i+1].num),t[i+1].size=t[i+1].len=1;
t[n+2].size=t[n+2].len=1;
tot=n+2;
root=build(1,n+2);
while(m--){
int opt;
scanf("%d",&opt);
switch(opt){
case 0:{
int p,a,b;
scanf("%d%d%d",&p,&a,&b);
int cur=split(p+1,p);
t[++tot].fa=cur;t[cur].ch[0]=tot;
t[tot].num=a;t[tot].len=t[tot].size=b-a+1;
pushup(cur);pushup(root);
break;
}
case 1:{
int a,b;
scanf("%d%d",&a,&b);
int cur=split(a,b);
t[t[cur].ch[0]].fa=t[cur].ch[0]=0;
pushup(cur);
pushup(root);
break;
}
case 2:{
int p;scanf("%d",&p);
int cur=split(p,p);
printf("%d\n",t[t[cur].ch[0]].num);
break;
}
}
}
return 0;
}
