标签:复杂度 can pre new print 而且 delete 树套树 stream
来一发树套树。1A也是很感动QAQ
就是时间复杂度略大。而且好像还有其他打法。
谨以此纪念此类型树套树入门
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define N 51000
#define size(x) ((x)?(x->size):(0))
#define lc(x) (x->ch[0])
#define rc(x) (x->ch[1])
int n,m;
struct Treap{
Treap *ch[2];
int v,key,size;
Treap(int x=0){
ch[0]=ch[1]=NULL;key=rand();size=1;v=x;
}
}*root[N*4];
void pushup(Treap *rt){
rt->size=size(lc(rt))+size(rc(rt))+1;
}
void turn(Treap *&rt,int d){
Treap *t=rt->ch[d^1];
rt->ch[d^1]=t->ch[d];
pushup(rt);
t->ch[d]=rt;
pushup(t);
rt=t;
}
void insert(Treap *&rt,int x){
if(!rt){
rt=new Treap(x);return;
}
int d=x < rt->v;
insert(rt->ch[d^1],x);
pushup(rt);
if(rt->key > rt->ch[d^1]->key) turn(rt,d);
}
void del(Treap *&rt,int x){
if(rt->v == x){
if(lc(rt)&&rc(rt)){
int d=lc(rt)->key < rc(rt)->key;
turn(rt,d);
del(rt->ch[d],x);
}
else{
Treap *t=NULL;
if(lc(rt)) t=lc(rt);
else t=rc(rt);
delete rt;rt=t;
}
}
else{
int d=rt->v < x;
del(rt->ch[d],x);
}
if(rt) pushup(rt);
}
int pai(Treap *&rt,int x){
if(!rt) return 0;
if(x<= rt->v){
return pai(lc(rt),x);
}
else return size(lc(rt))+1+pai(rc(rt),x);
}
int a[N];
void Insert(int l,int r,int rt){
pos(i,l,r) insert(root[rt],a[i]);
}
void build(int l,int r,int rt){
Insert(l,r,rt);
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
}
void update(int l,int r,int pos,int x,int y,int rt){
del(root[rt],x);insert(root[rt],y);
if(l==r) return;
int mid=(l+r)>>1;
if(pos<=mid) update(l,mid,pos,x,y,rt<<1);
else update(mid+1,r,pos,x,y,rt<<1|1);
}
int Pai(int xl,int xr,int k,int l,int r,int rt){
if(l>=xl&&r<=xr) return pai(root[rt],k);
int mid=(l+r)>>1;
int ans(0);
if(xl<=mid) ans+=Pai(xl,xr,k,l,mid,rt<<1);
if(xr>mid) ans+=Pai(xl,xr,k,mid+1,r,rt<<1|1);
return ans;
}
int kth(int L,int R,int k){
int l=0,r=(int)1e8;
while(l<=r){
int mid=(l+r)>>1;
if(Pai(L,R,mid,1,n,1)+1<=k) l=mid+1;
else r=mid-1;
}
return r;
}
int main(){
scanf("%d%d",&n,&m);
pos(i,1,n) scanf("%d",&a[i]);
build(1,n,1);
pos(i,1,m){
int opt;scanf("%d",&opt);
int l,r,k;
if(opt==3){
scanf("%d%d",&l,&k);
update(1,n,l,a[l],k,1);
a[l]=k;
continue;
}
scanf("%d%d%d",&l,&r,&k);
if(opt==1) printf("%d\n",Pai(l,r,k,1,n,1)+1);
else if(opt==2) printf("%d\n",kth(l,r,k));
else if(opt==4) printf("%d\n",kth(l,r,Pai(l,r,k,1,n,1)));
else if(opt==5) printf("%d\n",kth(l,r,Pai(l,r,k+1,1,n,1)+1));
}
return 0;
}
标签:复杂度 can pre new print 而且 delete 树套树 stream
原文地址:http://www.cnblogs.com/Hallmeow/p/7953775.html