O(nlogn),可分裂合并的线段树
嗨呀,写死我了
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<set>
#define Sum(a) ((a)?(a)->sum:0)
using namespace std;
struct tree{
tree* l,* r;
int sum;
tree(){l=r=0;sum=0;}
void update(){
sum=Sum(l)+Sum(r);
}
};
struct data{
int l,r,type;
tree* ptr;
data(int l,int r,int type,tree*ptr):
l(l),r(r),type(type),ptr(ptr){}
int operator<(const data& d)const{
return r<d.r;
}
};
typedef set<data>::iterator sit;
tree* merge(tree*& a,tree* b,int l,int r){
// printf("[%d,%d]",a,b);
if(!a)return b;
if(!b)return a;
if(l==r){
a->sum+=b->sum;
return a;
}
int mid=l+r>>1;
a->l=merge(a->l,b->l,l,mid);
a->r=merge(a->r,b->r,mid+1,r);
a->update();
return a;
}
tree* split(tree*& a,int l,int r,int k){
if(!k||!a)return 0;
// printf(" S{%d,%d,%d}",a,l,r);
if(l==r){
tree* ret=new tree;
ret->sum=a->sum;
a=0;
return ret;
}
tree* ret=new tree;
int mid=l+r>>1;
if(Sum(a->l)<k){
tree* f=split(a->r,mid+1,r,k-Sum(a->l));
ret->r=f,ret->l=a->l,a->l=0;
// printf("[%d,%d,%d]",a->l,f,k);
ret->update();
a->update();
} else {
tree* f=split(a->l,l,mid,k);
ret->l=f,ret->r=0;
ret->update();
a->update();
}
// printf("{%d}\n",k);
return ret;
}
void insert(tree*& a,int l,int r,int k){
if(!a)a=new tree;
a->sum++;
if(l==r)return ;
int mid=l+r>>1;
if(k<=mid)insert(a->l,l,mid,k);
else insert(a->r,mid+1,r,k);
}
int ask(tree* a,int l,int r,int k){
// printf("[%d,%d]",a->sum,k);
if(l==r)return l;
int mid=l+r>>1;
if(Sum(a->l)<k)return ask(a->r,mid+1,r,k-Sum(a->l));
else return ask(a->l,l,mid,k);
}
tree* newnode(int k,int n){
tree* ret=0;
insert(ret,1,n,k);
return ret;
}
void print(tree* a,int l,int r,bool type){
if(!a)return ;
if(l==r){
printf("%d ",l);
return ;
}
int mid=l+r>>1;
if(type){
print(a->r,mid+1,r,type);
print(a->l,l,mid,type);
} else {
print(a->l,l,mid,type);
print(a->r,mid+1,r,type);
}
}
int n,m;
set<data>st;
int main(){
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1,a;i<=n;++i)
scanf("%d",&a),st.insert(data(i,i,0,newnode(a,n)));
for(int i=1,k,op,l,r;i<=m;++i){
scanf("%d%d%d",&op,&l,&r);
tree* res=0;
sit it=st.lower_bound(data(0,l,0,0));
while(it!=st.end()&&it->l<=r){
data d=*it;
sit xt=it;xt++;
st.erase(it);it=xt;
tree* g=d.ptr;
if(d.l<=l&&r<=d.r){
if(op==d.type){
st.insert(data(d.l,d.r,d.type,g));
goto end;
} else if(d.type){
tree* ptr=split(g,1,n,d.r-r);
res=split(g,1,n,r-l+1);
if(Sum(g)!=0)st.insert(data(d.l,l-1,d.type,g));
if(Sum(ptr)!=0)st.insert(data(r+1,d.r,d.type,ptr));
} else {
tree* ptr=split(g,1,n,l-d.l);
res=split(g,1,n,r-l+1);
if(Sum(ptr)!=0)st.insert(data(d.l,l-1,d.type,ptr));
if(Sum(g)!=0)st.insert(data(r+1,d.r,d.type,g));
}
st.insert(data(l,r,op,res));
goto end;
} else if(l<=d.l&&d.r<=r){
res=merge(res,g,1,n);
} else if(d.l<l){
if(d.type){
k=d.r-l+1;
tree* ptr=split(g,1,n,k);
res=merge(res,ptr,1,n);
if(Sum(g)!=0)st.insert(data(d.l,l-1,d.type,g));
} else {
k=l-d.l;
tree* ptr=split(g,1,n,k);
res=merge(res,g,1,n);
if(Sum(ptr)!=0)st.insert(data(d.l,l-1,d.type,ptr));
}
} else if(d.r>r){
if(d.type){
k=d.r-r;
tree* ptr=split(g,1,n,k);
res=merge(res,g,1,n);
if(Sum(ptr)!=0)st.insert(data(r+1,d.r,d.type,ptr));
} else {
k=r-d.l+1;
tree* ptr=split(g,1,n,k);
res=merge(res,ptr,1,n);
if(Sum(g)!=0)st.insert(data(r+1,d.r,d.type,g));
}
}
}
st.insert(data(l,r,op,res));
end:;
}
int q;scanf("%d",&q);
sit it=st.lower_bound(data(q,q,0,0));
if(!it->type)printf("%d",ask(it->ptr,1,n,q-it->l+1));
else printf("%d",ask(it->ptr,1,n,it->r-q+1));
}