树套树-线段树套平衡树
树套树-线段树套平衡树
这个代码写起来真心累。。。
今天反正是不想再写一遍了
虽然好像十分无脑的样子。。。
思路十分简单,实现十分自然。。。
bzoj 3196 二逼平衡树
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long,long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++)
#define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--)
ll read(){
ll x=0,f=1;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
#define lc (i<<1)
#define rc (i<<1|1)
const int maxn=50050;
struct Node{
int l,r,root;
} tr[maxn*3];
int n,m,a[maxn],b[maxn],tot;
struct TreapNode{
int ls,rs,val,rnd,sz;
} treap[maxn*20];
int sta[maxn],top;
int newnode(int v){
treap[++tot].val=v;treap[tot].rnd=rand();
treap[tot].sz=1;treap[tot].ls=treap[tot].rs=0;
return tot;
}
void update(int i){
treap[i].sz=treap[treap[i].ls].sz+treap[treap[i].rs].sz+1;
}
void build(int i,int l,int r){
tr[i].l=l,tr[i].r=r;
if(l==r){
tr[i].root=newnode(a[l]);
return;
}
rep(k,l,r) b[k]=a[k];
sort(b+l,b+r+1);
int nw=0,pre=0;top=0;
rep(k,l,r){
nw=newnode(b[k]);pre=0;
while(top && treap[sta[top]].rnd>treap[nw].rnd){
update(sta[top]);
pre=sta[top];
sta[top--]=0;
}
if(top) treap[sta[top]].rs=nw;
treap[nw].ls=pre;sta[++top]=nw;
}
while(top) update(sta[top--]);
tr[i].root=sta[1];
int md=(l+r)>>1;
build(lc,l,md);build(rc,md+1,r);
}
void split(int &x,int &y,int val,int nw){
if(nw==0){x=y=0;return;}
if(treap[nw].val<=val){
x=nw;split(treap[x].rs,y,val,treap[x].rs);
}
else{
y=nw;split(x,treap[y].ls,val,treap[y].ls);
}
update(nw);
}
int merge(int x,int y){
if(!x || !y) return x+y;
int nw;
if(treap[x].rnd<treap[y].rnd){
treap[x].rs=merge(treap[x].rs,y);
update(x);return x;
}
else{
treap[y].ls=merge(x,treap[y].ls);
update(y);return y;
}
}
int fnd1(int i,int v){
int x,y;
split(x,y,v-1,tr[i].root);
int ret=treap[x].sz;
//cerr<<treap[x].val<<' '<<treap[treap[x].ls].val<<' '<<treap[x].ls<<' '<<treap[x].rs<<endl;
tr[i].root=merge(x,y);return ret;
}
int ask1(int i,int l,int r,int L,int R,int v){
if(l>=L && r<=R){
int ret=fnd1(i,v);
// cerr<<l<<' '<<r<<' '<<ret<<endl;
return ret;
}
if(l>R || r<L) return 0;
int md=(l+r)>>1;
return ask1(lc,l,md,L,R,v)+ask1(rc,md+1,r,L,R,v);
}
int query1(int l,int r,int k){
int ret=ask1(1,1,n,l,r,k)+1;
//cerr<<l<<' '<<r<<' '<<k<<' '<<ret<<endl;
return ret;
}
int query2(int l,int r,int k){
int L=0,R=100000000;
while(L+1<R){
int md=(L+R)>>1;
int num=query1(l,r,md);
if(num<=k) L=md;
else R=md-1;
// cout<<md<<"is"<<num<<endl;
}
int num=query1(l,r,L+1);
if(num<=k) return L+1;
else return L;
}
void modify(int i,int l,int r,int pos,int v1,int v2){
int x,y,z;
split(x,z,v2,tr[i].root);
split(x,y,v2-1,x);
y=merge(treap[y].ls,treap[y].rs);
tr[i].root=merge(merge(x,y),z);
split(x,y,v1,tr[i].root);
tr[i].root=merge(merge(x,newnode(v1)),y);
if(l==r) return;
int md=(l+r)>>1;
if(pos<=md) modify(lc,l,md,pos,v1,v2);
else modify(rc,md+1,r,pos,v1,v2);
}
void change(int pos,int v1,int v2){
modify(1,1,n,pos,v1,v2);
}
int fnd4(int i,int v){
int nw=tr[i].root,x,y;
split(x,y,v-1,nw);
int nod=x;
while(treap[nod].rs) nod=treap[nod].rs;
int ret=treap[nod].val;
tr[i].root=merge(x,y);
return ret;
}
int ask4(int i,int l,int r,int L,int R,int v){
if(l>=L && r<=R) return fnd4(i,v);
if(l>R || r<L) return -1e9;
int md=(l+r)>>1;
return max(ask4(lc,l,md,L,R,v),ask4(rc,md+1,r,L,R,v));
}
int query4(int l,int r,int k){
return ask4(1,1,n,l,r,k);
}
int fnd5(int i,int v){
int nw=tr[i].root,x,y;
split(x,y,v,nw);
int nod=y;
while(treap[nod].ls) nod=treap[nod].ls;
int ret=treap[nod].val;if(nod==0) ret=1e9;
tr[i].root=merge(x,y);
return ret;
}
int ask5(int i,int l,int r,int L,int R,int v){
if(l>=L && r<=R) return fnd5(i,v);
if(l>R || r<L) return 1e9;
int md=(l+r)>>1;
return min(ask5(lc,l,md,L,R,v),ask5(rc,md+1,r,L,R,v));
}
int query5(int l,int r,int k){
return ask5(1,1,n,l,r,k);
}
int main(){
srand(20020709);
//freopen("in","r",stdin);
n=read(),m=read();
rep(i,1,n) a[i]=read();
build(1,1,n);
while(m--){
int op=read();
if(op==1){
int l=read(),r=read(),k=read();
printf("%d\n",query1(l,r,k));
}
else if(op==2){
int l=read(),r=read(),k=read();
printf("%d\n",query2(l,r,k));
}
else if(op==3){
int pos=read(),v=read();
change(pos,v,a[pos]);
a[pos]=v;
}
else if(op==4){
int l=read(),r=read(),k=read();
printf("%d\n",query4(l,r,k));
}
else{
int l=read(),r=read(),k=read();
printf("%d\n",query5(l,r,k));
}
}
return 0;
}
/*
9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5
*/