BZOJ 3196: Tyvj 1730 二逼平衡树|线段树套平衡树

第一次写真正的树套树:线段树套平衡树?!(平衡树套线段树?!)
线段树维护的是区间,然后对于线段树维护的区间的所有数字都维护一个平衡树,然后所有的操作都对每个平衡树单独处理。
比如说操作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;
}

你可能感兴趣的:(线段树套平衡树)