loj #106. 二逼平衡树

#106. 二逼平衡树

内存限制:512 MiB时间限制:4000 ms标准输入输出
题目类型:传统评测方式:文本比较
 题目描述

这是一道模板题。

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:

  1. 查询 x  在区间内的排名;
  2. 查询区间内排名为 k 的值;
  3. 修改某一位置上的数值;
  4. 查询 x 在区间内的前趋(前趋定义为小于 x,且最大的数);
  5. 查询 x 在区间内的后继(后继定义为大于 x ,且最小的数)。
输入格式

第一行两个数 n,m,表示长度为 n 的有序序列和 m 个操作。
第二行有 n个数,表示有序序列。

下面有 m行,每行第一个数表示操作类型:

  1. 之后有三个数 l,r,x表示查询 x 在区间 [l,r]的排名;
  2. 之后有三个数 l,r,k 表示查询区间 [l,r] 内排名为 k 的数;
  3. 之后有两个数 pos,x表示将 pos位置的数修改为 x
  4. 之后有三个数 l,r,x 表示查询区间 [l,r]内 x的前趋;
  5. 之后有三个数 l,r,x 表示查询区间 [l,r] 内 x的后继.
输出格式

对于操作 1,2,4,5各输出一行,表示查询结果。

样例
样例输入
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
样例输出
2
4
3
4
9
数据范围与提示

1≤n,m≤5e4  −1e8≤k,x≤1e8

#include <bits/stdc++.h>
#define pt ch[ch[root][1]][0]
const int MAXN=1e5+10;
const int inf=1e8+10;
using namespace std;
int n;
int ch[MAXN<<7][2],size[MAXN<<7],pre[MAXN<<7],key[MAXN<<7],cnt2=0,psize;
int rt[MAXN],a[MAXN];
vector<int>vec;
void Treavel(int x)
{
    if(x)
    {
        Treavel(ch[x][0]);
        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]);
        Treavel(ch[x][1]);
    }
}
void debug(int rp)
{
    printf("root:%d\n",rp);
    Treavel(rp);
}
typedef struct node{
    int root,maxx;
    void newnode(int &x,int fa,int vul){
        x=++cnt2;ch[x][0]=ch[x][1]=0;pre[x]=fa;key[x]=vul;
        size[x]=1;
    }
    void inte(){
        root=0;
        newnode(root,0,-inf);
        newnode(ch[root][1],root,inf);
    }
    void up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}
    void rotate(int x,int kind){
        int y=pre[x];
        ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y;
        if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
        pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
        up(y);
    }
    void splay(int x,int goal){
        while(pre[x]!=goal){
            if(pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x);
            else{
                int y=pre[x];int kind=ch[pre[y]][0]==y;
                if(ch[y][kind]==x) rotate(x,!kind),rotate(x,kind);
                else rotate(y,kind),rotate(x,kind);
            }
        }
        if(goal==0) root=x;
        up(x);
    }
    void insert(int &x,int vul,int fa){
        if(!x){newnode(x,fa,vul);return ;}
        if(key[x]>vul) insert(ch[x][0],vul,x);
        else insert(ch[x][1],vul,x);
        up(x);
    }
    int find1(int x,int vul){
        if(key[x]==vul) return x;
        else if(key[x]<vul) return find1(ch[x][1],vul);
        else return find1(ch[x][0],vul);
    }
    int find2(int x,int siz){
        if(siz==size[ch[x][0]]+1) return x;
        else if(siz<=size[ch[x][0]]) return find2(ch[x][0],siz);
        else return find2(ch[x][1],siz-size[ch[x][0]]-1);
    }
    void erase(int vul){
        splay(find1(root,vul),0);
        int t=size[ch[root][0]]+1;
        splay(find2(root,t-1),0);
        splay(find2(root,t+1),root);
        pre[ch[ch[root][1]][0]]=0;ch[ch[root][1]][0]=0;up(ch[root][1]);up(root);
    }
    void pre_vul(int x,int vul){
        if(!x) return ;
        if(key[x]>=vul) pre_vul(ch[x][0],vul);
        else{
            if(vul-key[x]<=vul-maxx) maxx=key[x],pre_vul(ch[x][1],vul);
            else pre_vul(ch[x][1],vul);
        }
    }
    void last_vul(int x,int vul){
        if(!x) return ;
        if(key[x]<=vul) last_vul(ch[x][1],vul);
        else{
            if(key[x]-vul<=maxx-vul) maxx=key[x],last_vul(ch[x][0],vul);
            else last_vul(ch[x][0],vul);
        }
    }
}node;
typedef struct wjy{
   int l,r,sum;
}wjy;
wjy dd[MAXN<<7];int cnt1=0;
typedef struct List{
    node T;
}List;
List d[MAXN<<2];
void built(int &x,int y,int l,int r,int vul,int flag){
    x=++cnt1;dd[x]=dd[y];dd[x].sum+=flag;
    if(l==r) return ;
    int mid=(l+r)>>1;
    if(vul<=mid) built(dd[x].l,dd[y].l,l,mid,vul,flag);
    else built(dd[x].r,dd[y].r,mid+1,r,vul,flag);
}
int ans;
vector<int>vv1;
vector<int>vv2;
int get_id(int x){return x&(-x);}
void slove(int l,int r){
    for(int i=l-1;i>0;i-=get_id(i)) vv2.push_back(rt[i]);
    for(int i=r;i>0;i-=get_id(i)) vv1.push_back(rt[i]);
}
int querty1(int l,int r,int ql,int qr,int vul){
    slove(ql,qr);
    while(l<r){
        int mid=(l+r)>>1;
        if(mid<=vul){
            l=mid+1;
            for(int i=0;i<vv1.size();i++) ans+=dd[dd[vv1[i]].l].sum;
            for(int i=0;i<vv2.size();i++) ans-=dd[dd[vv2[i]].l].sum;
            for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].r;
            for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].r;
        }
        else{
            r=mid;
            for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].l;
            for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].l;
        }

    }
    return ans;
}
int querty2(int l,int r,int ql,int qr,int k){
    slove(ql,qr);
    int t;
    while(l<r){
        int mid=(l+r)>>1;t=0;
        for(int i=0;i<vv1.size();i++) t+=dd[dd[vv1[i]].l].sum;
        for(int i=0;i<vv2.size();i++) t-=dd[dd[vv2[i]].l].sum;
        if(t>=k){
            r=mid;
            for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].l;
            for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].l;
        }
        else{
            l=mid+1;k-=t;
            for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].r;
            for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].r;
        }

    }
    return l;
}
void update1(int root,int l,int r,int vul,int t,int flag){
    //cout<<l<<" "<<r<<endl;
    //cout<<d[root].T.root<<endl;
    if(flag) d[root].T.insert(d[root].T.root,vul,0);
    else d[root].T.erase(vul);
    //if(!flag) debug(d[root].T.root);
    if(l==r)   return ;
    int mid=(l+r)>>1;
    if(t<=mid) update1(root<<1,l,mid,vul,t,flag);
    else update1(root<<1|1,mid+1,r,vul,t,flag);
}
int maxn;
void querty(int root,int l,int r,int ql,int qr,int x,int flag){
    if(ql<=l&&r<=qr){
        if(flag) d[root].T.maxx=-1*inf,d[root].T.pre_vul(d[root].T.root,x),maxn=max(maxn,d[root].T.maxx);
        else d[root].T.maxx=inf,d[root].T.last_vul(d[root].T.root,x),maxn=min(maxn,d[root].T.maxx);
        return ;
    }
    int mid=(l+r)>>1;
    if(ql<=mid) querty(root<<1,l,mid,ql,qr,x,flag);
    if(qr>mid) querty(root<<1|1,mid+1,r,ql,qr,x,flag);
}
void inte(){
    for(int i=1;i<=(n<<2);i++) d[i].T.inte();
    for(int i=1;i<=n;i++){
        for(int j=i;j<=n;j+=get_id(j)){
            built(rt[j],rt[j],1,psize,a[i],1);

        }
        update1(1,1,n,a[i],i,1);
    }
}
void update(int pos,int x,int y){
    for(int j=pos;j<=n;j+=get_id(j)){
        built(rt[j],rt[j],1,psize,x,-1);
        built(rt[j],rt[j],1,psize,y,1);
    }
    update1(1,1,n,x,pos,0);
    //cout<<"sb"<<endl;
    update1(1,1,n,y,pos,1);
    //cout<<"sb"<<endl;
}
int slove1(int l,int r,int x){
    ans=0;
    int ans1=querty1(1,psize,l,r,x-1);
    vv1.clear();vv2.clear();
    return ans1+1;
}
int slove2(int l,int r,int k){
    ans=querty2(1,psize,l,r,k);
    vv1.clear();vv2.clear();
    return ans;
}
int slove3(int l,int r,int x){
    maxn=-1*inf;querty(1,1,n,l,r,x,1);
    return maxn;
}
int slove4(int l,int r,int x){
    //cout<<l<<" "<<r<<endl;
    maxn=inf;querty(1,1,n,l,r,x,0);
    return maxn;
}
typedef struct P{
  int op,l,r,x;
}P;
P p[MAXN];
int main(){
    int m;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),vec.push_back(a[i]);
    for(int i=1;i<=m;i++){
        scanf("%d",&p[i].op);
        if(p[i].op==3) scanf("%d%d",&p[i].l,&p[i].x),vec.push_back(p[i].x);
        else if(p[i].op==2) scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].x);
        else scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].x),vec.push_back(p[i].x);
    }
    sort(vec.begin(),vec.end());
    psize=unique(vec.begin(),vec.end())-vec.begin();
    for(int i=1;i<=n;i++) a[i]=lower_bound(vec.begin(),vec.begin()+psize,a[i])-vec.begin()+1;
    inte();
    for(int i=1;i<=m;i++){
        if(p[i].op==2) continue;
        p[i].x=lower_bound(vec.begin(),vec.begin()+psize,p[i].x)-vec.begin()+1;
    }
    for(int i=1;i<=m;i++){
        if(p[i].op==1) printf("%d\n",slove1(p[i].l,p[i].r,p[i].x));
        else if(p[i].op==2) printf("%d\n",vec[slove2(p[i].l,p[i].r,p[i].x)-1]);
        else if(p[i].op==3) update(p[i].l,a[p[i].l],p[i].x),a[p[i].l]=p[i].x;
        else if(p[i].op==4) printf("%d\n",vec[slove3(p[i].l,p[i].r,p[i].x)-1]);
        else printf("%d\n",vec[slove4(p[i].l,p[i].r,p[i].x)-1]);
    }
    return 0;
}

  

转载于:https://www.cnblogs.com/wang9897/p/8708163.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值