bzoj 3678 wangxz与OJ

3678: wangxz与OJ

Time Limit: 10 Sec  Memory Limit: 128 MB
http://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

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

 

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/6834504.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值