返回顶部
大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

3678: wangxz与OJ

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

Sample Output

2

HINT

Source

From LiZitong

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;
}
View Code

 

posted @ 2019-08-15 19:36  plysc  阅读(175)  评论(0编辑  收藏  举报