第一次写真正的树套树:线段树套平衡树?!(平衡树套线段树?!)
线段树维护的是区间,然后对于线段树维护的区间的所有数字都维护一个平衡树,然后所有的操作都对每个平衡树单独处理。
比如说操作3,需要先二分答案,然后再询问每个区间的平衡树来 judge
这样的复杂度是 log3n 的,感觉好暴力!!分块什么的肯定也可以搞一搞。
树状数组套主席树怎么没人写,真的会MLE吗
好久没写4K以上的代码了~
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<iostream>
#define N 220050
#define M 4000001
using namespace std;
int sc()
{
int i=0,f=1; char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
return i*f;
}
int ch[M][2],rnd[M],v[M],s[M],w[M];
int root[N],a[N],n,m;
int cnt;
void updata(int k){s[k]=s[ch[k][0]]+s[ch[k][1]]+w[k];}
void Turn(int &x,bool e)
{
int t=ch[x][!e];
ch[x][!e]=ch[t][e];
ch[t][e]=x;
s[t]=s[x];
updata(x);
x=t;
}
void insert(int &x,int f)
{
if(!x)
{
x=++cnt;
s[x]=w[x]=1;
v[x]=f;
rnd[x]=rand();
return;
}
s[x]++;
if(f==v[x])w[x]++;
else if(f<v[x])
{
insert(ch[x][0],f);
if(rnd[ch[x][0]]<rnd[x])Turn(x,1);
}
else
{
insert(ch[x][1],f);
if(rnd[ch[x][1]]<rnd[x])Turn(x,0);
}
}
void del(int &x,int f)
{
if(v[x]==f)
{
if(w[x]>1)
{
w[x]--;
s[x]--;
return;
}
if(ch[x][0]*ch[x][1]==0)x=ch[x][0]+ch[x][1];
else if(rnd[ch[x][0]]<rnd[ch[x][1]])
Turn(x,1),del(x,f);
else
Turn(x,0),del(x,f);
}
else if(f<v[x])
del(ch[x][0],f),s[x]--;
else
del(ch[x][1],f),s[x]--;
}
void build(int x,int l,int r,int p,int f)
{
insert(root[x],f);
if(l==r)return;
int mid=l+r>>1;
if(p<=mid) build(x<<1,l,mid,p,f);
else build(x<<1|1,mid+1,r,p,f);
}
int ask_rank(int x,int f)
{
if(!x)return 0;
if(f==v[x])return s[ch[x][0]];
else if(f<v[x])return ask_rank(ch[x][0],f);
else return s[ch[x][0]]+w[x]+ask_rank(ch[x][1],f);
}
int get_rank(int x,int L,int R,int l,int r,int f)
{
if(L==l&&R==r)return ask_rank(root[x],f);
int mid=L+R>>1;
if(r<=mid)return get_rank(x<<1,L,mid,l,r,f);
else if(l>mid)return get_rank(x<<1|1,mid+1,R,l,r,f);
else return get_rank(x<<1,L,mid,l,mid,f)+get_rank(x<<1|1,mid+1,R,mid+1,r,f);
}
int search(int l,int r,int x)
{
int L=0,R=1e9,ans;
while(L<=R)
{
int mid=L+R>>1;
if(get_rank(1,1,n,l,r,mid)<x) ans=mid,L=mid+1;
else R=mid-1;
}
return ans;
}
void change(int x,int L,int R,int p,int k,int f)
{
del(root[x],f);
insert(root[x],k);
if(L==R)return;
int mid=L+R>>1;
if(p<=mid)change(x<<1,L,mid,p,k,f);
else change(x<<1|1,mid+1,R,p,k,f);
}
int pre(int x,int f)
{
if(!x)return 0;
if(v[x]<f) return max(v[x],pre(ch[x][1],f));
else return pre(ch[x][0],f);
}
int nxt(int x,int f)
{
if(!x)return 1e9;
if(v[x]>f) return min(v[x],nxt(ch[x][0],f));
else return nxt(ch[x][1],f);
}
int ask_pre(int x,int L,int R,int l,int r,int f)
{
if(L==l&&R==r)return pre(root[x],f);
int mid=(L+R)>>1;
if(r<=mid)return ask_pre(x<<1,L,mid,l,r,f);
else if(l>mid)return ask_pre(x<<1|1,mid+1,R,l,r,f);
else return max(ask_pre(x<<1,L,mid,l,mid,f),ask_pre(x<<1|1,mid+1,R,mid+1,r,f));
}
int ask_nxt(int x,int L,int R,int l,int r,int f)
{
if(L==l&&R==r)return nxt(root[x],f);
int mid=L+R>>1;
if(r<=mid)return ask_nxt(x<<1,L,mid,l,r,f);
else if(l>mid)return ask_nxt(x<<1|1,mid+1,R,l,r,f);
else return min(ask_nxt(x<<1,L,mid,l,mid,f),ask_nxt(x<<1|1,mid+1,R,mid+1,r,f));
}
int main()
{
n=sc(),m=sc();
for(int i=1;i<=n;i++)a[i]=sc();
for(int i=1;i<=n;i++)build(1,1,n,i,a[i]);
for(int i=1;i<=m;i++)
{
int f=sc();
if(f==1)
{
int l=sc(),r=sc(),x=sc();
printf("%d\n",get_rank(1,1,n,l,r,x)+1);
}
else if(f==2)
{
int l=sc(),r=sc(),x=sc();
printf("%d\n",search(l,r,x));
}
else if(f==3)
{
int x=sc(),y=sc();
change(1,1,n,x,y,a[x]),a[x]=y;
}
else if(f==4)
{
int l=sc(),r=sc(),x=sc();
printf("%d\n",ask_pre(1,1,n,l,r,x));
}
else if(f==5)
{
int l=sc(),r=sc(),x=sc();
printf("%d\n",ask_nxt(1,1,n,l,r,x));
}
}
return 0;
}