[ 线段树套treap ] [ TJOI2016&&HEOI2016 ] BZOJ4552

来源:互联网 发布:淘宝货源上架数据包 编辑:程序博客网 时间:2024/06/05 02:37

题解

#include<bits/stdc++.h>using namespace std;inline char nc(){    static char buf[100000],*p1=buf,*p2=buf;    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void Read(int& x){    char c=nc();    for(;c<'0'||c>'9';c=nc());    for(x=0;c>='0'&&c<='9';x=x*10+c-48,c=nc());}typedef pair<int,int> abcd;const int N=2000010;const int M=10000010;int rrtt=127;int k,p,n,m;int a[N];int x,y,z,Q;int rt=1,cnt=1,Rt[N],ch[N][2],sz[N];int num,c[M],ls[M],rs[M];int tmp,S;int st[M],top;bool d[N];inline int new_node(){    return st[top--];}inline void erase(int x){    ls[x]=rs[x]=c[x]=0;    st[++top]=x;}void Update(int& x,int l,int r,int y){    x=new_node();    c[x]++;    if(l==r)return;    int Mid=l+r>>1;    if(y<=Mid)Update(ls[x],l,Mid,y);else Update(rs[x],Mid+1,r,y);}int Query(int x,int l,int r,int y){    if(l==r)return l;    int Mid=l+r>>1;    if(c[ls[x]]>=y)return Query(ls[x],l,Mid,y);    return Query(rs[x],Mid+1,r,y-c[ls[x]]);}void split(int x,int& y,int k){    y=new_node();    if(k<c[ls[x]])split(ls[x],ls[y],k);else{        swap(ls[x],ls[y]);        if(k>c[ls[y]])split(rs[x],rs[y],k-c[ls[y]]);    }    c[y]=k;c[x]-=k;}void merge(int& x,int y){    if(!x||!y)return void(x+=y);    merge(ls[x],ls[y]);merge(rs[x],rs[y]);    c[x]=c[ls[x]]+c[rs[x]];erase(y);}inline int Rand(){    rrtt=23333333ll*rrtt%1000000007;    return rrtt&1;}inline void New_node(int x,bool D){    a[++cnt]=x;sz[cnt]=x;d[cnt]=D;}inline void Up(int x){    sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+a[x];}int Merge(int x,int y){    if(!x||!y)return x+y;    if(Rand()){        ch[x][1]=Merge(ch[x][1],y);        Up(x);        return x;    }    ch[y][0]=Merge(x,ch[y][0]);Up(y);    return y;}int Find(int x,int y){    y-=sz[ch[x][0]];    if(y<=0)return Find(ch[x][0],y+sz[ch[x][0]]);    if(y<=a[x]){        S+=sz[ch[x][0]];        return x;    }    S+=sz[ch[x][0]]+a[x];    return Find(ch[x][1],y-a[x]);}abcd Split(int x,int y){    if(!x)return abcd(0,0);    abcd tmp;    if(y<sz[ch[x][0]]+a[x])    tmp=Split(ch[x][0],y),ch[x][0]=tmp.second,Up(x),tmp.second=x;    else tmp=Split(ch[x][1],y-sz[ch[x][0]]-a[x]),ch[x][1]=tmp.first,Up(x),tmp.first=x;    return tmp;}inline void Work(int p){    if(!p)return;    S=0;    int x=Find(rt,p);    if(S+a[x]==p)return;    abcd X=Split(rt,S);    abcd Y=Split(X.second,a[x]);    if(!d[x]){        New_node(p-S,0);        split(Rt[x],Rt[cnt],p-S);        New_node(a[x]-p+S,0);        Rt[cnt]=Rt[x];        rt=Merge(X.first,Merge(cnt-1,Merge(cnt,Y.second)));    }else{        int tmp;        New_node(p-S,1);        split(Rt[x],tmp,a[x]-p+S);        Rt[cnt]=Rt[x];        New_node(a[x]-p+S,1);        Rt[cnt]=tmp;        rt=Merge(X.first,Merge(cnt-1,Merge(cnt,Y.second)));    }}void Traver(int x){    if(!x)return;    Traver(ch[x][0]);    Traver(ch[x][1]);    if(ch[x][0])merge(Rt[x],Rt[ch[x][0]]);    if(ch[x][1])merge(Rt[x],Rt[ch[x][1]]);}int main(){    Read(n);Read(Q);    for(int i=1;i<M;i++)st[++top]=i;    for(int i=1;i<=n;i++){        Read(x);New_node(1,0);        rt=Merge(rt,cnt);        Update(Rt[cnt],1,n,x);    }    while(Q--){        Read(k);Read(x);Read(y);        Work(x-1);Work(y);        abcd X=Split(rt,x-1);        abcd Y=Split(X.second,y-x+1);        Traver(Y.first);        New_node(y-x+1,k);        Rt[cnt]=Rt[Y.first];        rt=Merge(X.first,Merge(cnt,Y.second));    }    Read(x);    S=0;tmp=Find(rt,x);x-=S;    if(!d[tmp])printf("%d\n",Query(Rt[tmp],1,n,x));    else printf("%d\n",Query(Rt[tmp],1,n,a[tmp]-x+1));    return 0;}
阅读全文
0 0