线段树合并写了不少 分裂是第一次
直接每一个有序区间用一棵权值线段树维护有哪些数
外层用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;
}