[Treap套权值线段树 线段树分裂与合并] BZOJ 4552 [Tjoi2016&Heoi2016]排序

线段树合并写了不少 分裂是第一次
直接每一个有序区间用一棵权值线段树维护有哪些数
外层用treap维护顺序
然后排序就把代表这段的很多颗线段树合并在一起 两端处会割开某个有序区间 会涉及分裂操作

#include
#include
#include
using namespace std;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
  return *p1++;
}

inline void read(int &x){
  char c=nc(),b=1;
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int M=9999999;
int Stack[M+5],pnt;
int ls[M],rs[M],s[M];
inline void init(){ for (int i=M-1;i;i--) Stack[++pnt]=i; }
inline int newn(){ return Stack[pnt--]; }
inline void eras(int x){ s[x]=ls[x]=rs[x]=0; Stack[++pnt]=x; }
inline void build(int &x,int l,int r,int t){
  x=newn(); s[x]++;
  if (l==r) return; int mid=(l+r)>>1;
  if (t<=mid) build(ls[x],l,mid,t);
  else build(rs[x],mid+1,r,t);
}
inline void merge(int &x,int y){
  if (!x||!y) return void(x=x+y);
  merge(ls[x],ls[y]);
  merge(rs[x],rs[y]);
  s[x]=s[ls[x]]+s[rs[x]]; eras(y);
}
inline void split(int x,int &y,int k){
  y=newn();
  if (k>s[ls[x]]) split(rs[x],rs[y],k-s[ls[x]]); else swap(rs[x],rs[y]);
  if (kinline int query(int x,int l,int r,int k){
  if (l==r) return l; int mid=(l+r)>>1;
  if (k<=s[ls[x]]) return query(ls[x],l,mid,k);
  else return query(rs[x],mid+1,r,k-s[ls[x]]);
}

const int N=600005;

struct node{
  int root,dir,cnt,sum; int size;
  node *l,*r;
  void newnode(int ro,int d,int c) { root=ro; dir=d; cnt=sum=c; size=1; l=r=NULL; }
  void update(){
    sum=cnt; size=1;
    if (l) { sum+=l->sum; size+=l->size; }
    if (r) { sum+=r->sum; size+=r->size; }
  }
}nodes[N],*Root;
int ncnt;
inline int Size(node *x){ return x?x->size:0; }  
inline int Sum(node *x){ return x?x->sum:0; }  
inline int ran(){ static int x=31253125; x+=(x<<4)+1; return x&65536; }  

inline node* Merge(node* A,node *B){
  if (!A||!B) return A?A:B;
  if (ran()){  
    node *y=Merge(A->r,B); A->r=y; A->update(); return A;  
  }else{  
    node *y=Merge(A,B->l); B->l=y; B->update(); return B;  
  }  
}
typedef pair Droot;
inline Droot Split(node *x,int k){
  if (!x) return Droot(NULL,NULL);  
  Droot y;  
  if(Size(x->l)>=k)
    y=Split(x->l,k),x->l=y.second,x->update(),y.second=x;  
  else  
    y=Split(x->r,k-Size(x->l)-1),x->r=y.first,x->update(),y.first=x;   
  return y;  
}
int tk; node* tp;
inline int Find(int k){  
  node *x=Root; int ret=0;  
  while (1){  
    if (k>Sum(x->l) && k<=Sum(x->l)+x->cnt)  
      return (tk=k-Sum(x->l),tp=x),ret+Size(x->l)+1;  
    if (Sum(x->l)>=k)  
      x=x->l;  
    else  
      k-=Sum(x->l)+x->cnt,ret+=1+Size(x->l),x=x->r;  
  }  
}
inline void Travel(node *p){
  if (!p) return;
  Travel(p->l); Travel(p->r);
  if (p->l) merge(p->root,p->l->root);
  if (p->r) merge(p->root,p->r->root);
}

inline void Work(int k){
  if (!k) return;
  int p=Find(k);
  if (tk==tp->cnt) return;
  Droot x=Split(Root,p-1);  
  Droot y=Split(x.second,1);
  node *z=y.first;
  if (z->dir==0){
    int tem;
    split(z->root,tem,tk);
    node *w=nodes+(++ncnt);
    w->newnode(tem,0,s[tem]);
    z->newnode(z->root,0,s[z->root]);
    z=Merge(z,w);
    Root=Merge(x.first,Merge(z,y.second));
  }else{
    int tem;
    split(z->root,tem,z->cnt-tk);
    node *w=nodes+(++ncnt);
    w->newnode(tem,1,s[tem]);
    z->newnode(z->root,1,s[z->root]);
    z=Merge(w,z);
    Root=Merge(x.first,Merge(z,y.second));
  }
}

int n,m;

int main(){
  int x,d,l,r,q;
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  init();
  read(n); read(m);
  for (int i=1;i<=n;i++){
    read(x); node *p=nodes+(++ncnt);
    build(p->root,1,n,x);
    p->newnode(p->root,0,1);
    Root=Merge(Root,p);
  }
  while (m--){
    read(d); read(l); read(r);
    Work(l-1); Work(r);
    int lp=Find(l),rp=Find(r);  
    Droot x=Split(Root,lp-1);  
    Droot y=Split(x.second,rp-lp+1);
    Travel(y.first);
    node *p=nodes+(++ncnt);
    p->newnode(y.first->root,d,s[y.first->root]);
    Root=Merge(x.first,Merge(p,y.second));
  }
  read(q); Find(q);
  if (tp->dir==0)
    printf("%d\n",query(tp->root,1,n,tk));
  else
    printf("%d\n",query(tp->root,1,n,tp->cnt-tk+1));
  return 0;
}

你可能感兴趣的:(线段树,平衡树,树套树)