NKOJ 4340 (SCOI 2014)方伯伯的OJ (Splay+map+set)

来源:互联网 发布:js编码 编辑:程序博客网 时间:2024/05/08 18:12

P4340【SCOI2014】方伯伯的Oj

问题描述

这里写图片描述

输入格式

输入的第1行包含2个用空格分隔的整数n和m,表示初始用户数和操作数。
此后有m行,每行是一个询问,询问格式如上所示。

输出格式

输出包含m行。每行包含一个整数,其中第i行的整数表示第i个操作的输出。

样例输入

10 10
1 2 11
3 13
2 5
3 7
2 8
2 10
2 11
3 14
2 18
4 9

样例输出

2
2
2
4
3
5
5
7
8
11

提示

对于 100% 的数据,1 ≤ n ≤ 10^8,1 ≤ m ≤ 10^5

输入保证对于所有的操作 1,2,3,x 必然已经出现在队列中,同时对于所有操作 1,1 ≤ y ≤ 2 × 10^8,并且

y 没有出现在队列中。

对于所有操作 4,保证 1 ≤ k ≤ n。


此题强制在线,观察发现n很大,那么显然此题应该根据m入手,考虑将Splay中的点维护一个区间,然后查询到了再拆开成3个点。

需要维护两个值,编号和排名,按照排名建立Splay,用map记录编号区间为[a,b]的点,还需要记录当前已经被拆过的点即查找过的位置,这样就可以通过编号找到在Splay中对应的位置,然后还需要开一个map记录表示一个点的点。

然后每种操作找到对应的Splay的位置,拆点后直接处理即可。


代码:

#include<stdio.h>#include<iostream>#include<algorithm>#include<cstring>#include<map>#include<set>#define N 1000005using namespace std;struct node{    int l,r;    bool operator<(const node &b)const    {        if(l==b.l)return r<b.r;        return l<b.l;    }};set<int>A;map<int,int>C;map<node,int>B;set<int>::iterator Ai;map<node,int>::iterator Bi;int n,m;int rt,ls[N],rs[N],fa[N],id[N],lid[N],rid[N],v[N],si[N],tot;void MT(int x){si[x]=si[ls[x]]+si[rs[x]]+v[x];}void Zig(int x){    int y=fa[x],z=fa[y];    if(z)y==ls[z]?ls[z]=x:rs[z]=x;fa[x]=z;    ls[y]=rs[x];fa[rs[x]]=y;    rs[x]=y;fa[y]=x;    MT(y);MT(x);}void Zag(int x){    int y=fa[x],z=fa[y];    if(z)y==ls[z]?ls[z]=x:rs[z]=x;fa[x]=z;    rs[y]=ls[x];fa[ls[x]]=y;    ls[x]=y;fa[y]=x;    MT(y);MT(x);}void Splay(int x){    int y,z;    while(fa[x])    {        y=fa[x],z=fa[y];        if(z)        {            if(y==ls[z])x==ls[y]?(Zig(y),Zig(x)):(Zag(x),Zig(x));            else x==rs[y]?(Zag(y),Zag(x)):(Zig(x),Zag(x));        }        else x==ls[y]?Zig(x):Zag(x);    }    rt=x;}int Gmax(int p){    while(rs[p])p=rs[p];    return p;}int Gmin(int p){    while(ls[p])p=ls[p];    return p;}int Find(int x){    node tmp;    if(C.count(x))return C[x];    Ai=A.lower_bound(x);    tmp.r=*Ai-1;Ai--;    tmp.l=*Ai+1;    Bi=B.lower_bound(tmp);    return Bi->second;}int Div(int p,int x){    int l,r;node tmp;    Splay(p);    A.insert(x);    l=ls[p];r=rs[p];    fa[l]=fa[r]=ls[p]=rs[p]=0;    if(lid[p]<x-1)    {        tot++;        lid[tot]=lid[p];        rid[tot]=x-1;        v[tot]=x-lid[p];        fa[l]=tot;ls[tot]=l;        MT(tot);l=tot;        tmp.l=lid[l];        tmp.r=rid[l];        B[tmp]=l;    }    else if(lid[p]==x-1)    {        tot++;        id[tot]=lid[p];        v[tot]=1;        fa[l]=tot;        ls[tot]=l;        MT(tot);l=tot;        C[lid[p]]=tot;    }    if(x+1<rid[p])    {        tot++;        lid[tot]=x+1;        rid[tot]=rid[p];        v[tot]=rid[p]-x;        fa[r]=tot;rs[tot]=r;        MT(tot);r=tot;        tmp.l=lid[r];        tmp.r=rid[r];        B[tmp]=r;    }    else if(x+1==rid[p])    {        tot++;        id[tot]=x+1;        v[tot]=1;        fa[r]=tot;rs[tot]=r;        MT(tot);r=tot;        C[x+1]=tot;    }    fa[l]=fa[r]=++tot;    ls[tot]=l;rs[tot]=r;    id[tot]=x;v[tot]=1;    C[x]=tot;MT(tot);    return rt=tot;}void Del(int p){    int l=ls[p],r=rs[p];    fa[l]=fa[r]=ls[p]=rs[p]=0;    if(!l)rt=r;    else    {        l=Gmax(l);        Splay(l);        fa[r]=l;rs[l]=r;        rt=l;MT(l);    }}int Gkth(int k){    int p=rt;    while(p)    {        if(si[ls[p]]<k&&si[ls[p]]+v[p]>=k)return p;        if(si[ls[p]]>=k)p=ls[p];        else k-=si[ls[p]]+v[p],p=rs[p];    }    return p;}int main(){    int i,j,k,x,y,z,p,l,r,t;node tmp;    scanf("%d%d",&n,&m);int ans=0;    rt=++tot;lid[rt]=1;rid[rt]=n;v[rt]=si[rt]=n;    A.insert(0);A.insert(n+1);    tmp.l=1;tmp.r=n;B[tmp]=rt;    while(m--)    {        scanf("%d",&k);        if(k==1)        {            scanf("%d%d",&x,&y);            x-=ans;y-=ans;p=Find(x);            if(v[p]==1)            {                id[p]=y;C[y]=p;Splay(p);                ans=si[ls[p]]+1;                printf("%d\n",ans);            }            else            {                p=Div(p,x);id[p]=y;C[y]=p;                ans=si[ls[p]]+1;                printf("%d\n",ans);            }        }        if(k==2)        {            scanf("%d",&x);            x-=ans;p=Find(x);            if(v[p]==1)            {                Splay(p);                ans=si[ls[p]]+1;                printf("%d\n",ans);                Del(p);rs[p]=rt;fa[rt]=p;rt=p;            }            else            {                p=Div(p,x);                ans=si[ls[p]]+1;                printf("%d\n",ans);                Del(p);rs[p]=rt;fa[rt]=p;rt=p;            }        }        if(k==3)        {            scanf("%d",&x);            x-=ans;p=Find(x);            if(v[p]==1)            {                Splay(p);                ans=si[ls[p]]+1;                printf("%d\n",ans);                Del(p);ls[p]=rt;fa[rt]=p;rt=p;            }            else            {                p=Div(p,x);                ans=si[ls[p]]+1;                printf("%d\n",ans);                Del(p);ls[p]=rt;fa[rt]=p;rt=p;            }        }        if(k==4)        {            scanf("%d",&x);            x-=ans;p=Gkth(x);Splay(p);            if(v[p]==1)ans=id[p],printf("%d\n",ans);            else            {                t=x-si[ls[p]];                x=lid[p]+t-1;                p=Div(p,x);                ans=id[p];                printf("%d\n",ans);            }        }    }}