BZOJ 3196(Tyvj 1730 二逼平衡树-线段树套Treap)

8 篇文章 0 订阅
1 篇文章 0 订阅

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)
Input

第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继
Output

对于操作1,2,4,5各输出一行,表示查询结果
Sample Input
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
Sample Output
2

4

3

4

9
HINT

1.n和m的数据范围:n,m<=50000

2.序列中每个数的数据范围:[0,1e8]

3.虽然原题没有,但事实上5操作的k可能为负数

Source

建立线段树套平衡树

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <functional>
#include <cstdlib>
#include <queue>
#include <stack>
#include <set>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (20161119)
#define ALL(x) (x).begin(),(x).end()
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pri(a,n) for(int i=1;i<n;i++) cout<<a[i]<<' ';cout<<a[n]<<endl;
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (3023456)
int n,m;
struct treap{
    ll rnd[MAXN],v[MAXN],w[MAXN];
    int size[MAXN],l[MAXN],r[MAXN],cnt;
    void mem() {
        MEM(size) MEM(rnd) MEM(l) MEM(r) MEM(v) MEM(w)
        cnt=0;
    }
    void update(int x)
    {
        size[x]=size[l[x]]+size[r[x]]+w[x];
    }
    void rturn(int &k)
    {
        int t=l[k];l[k]=r[t];r[t]=k;update(k);update(t);k=t;
    }
    void lturn(int &k)
    {
        int t=r[k];r[k]=l[t];l[t]=k;update(k);update(t);k=t;
    }
    void insert(int &x,ll rank) 
    {
        if(!x)
        {
            x=++cnt;
            v[x]=rank; l[x]=r[x]=0;
            rnd[x]=rand();size[x]=w[x]=1;
            return ;
        }
        size[x]++;
        if(v[x]<rank)
        {
            insert(r[x],rank);
            if(rnd[r[x]]<rnd[x])lturn(x);
        }
        else if (v[x]>rank)
        {
            insert(l[x],rank);
            if(rnd[l[x]]<rnd[x]) rturn(x);
        }else w[x]++ ;
    }
    void del(int &x,ll val) {
        if (!x) return ;
        if (v[x]==val) {
            if (w[x]>1) {--w[x]; --size[x]; return; }
            if (!l[x]||!r[x]) x=l[x]+r[x];
            else if (rnd[l[x]]<rnd[r[x]]) rturn(x),del(x,val);
            else lturn(x),del(x,val);
        }
        else {
            --size[x];
            if (val<v[x]) del(l[x],val); else del(r[x],val);
        }
    }
    // return the pointer
    int lower_bound(int x,ll rank) {
        int ans=-1;
        if (!x) return ans;
        if (v[x]<=rank) {
            ans=lower_bound(r[x],rank);
            if (ans==-1) ans=x;
        } else ans=lower_bound(l[x],rank);
        return ans;
    }
    int upper_bound(int x,ll rank) {
        int ans=-1;
        if (!x) return ans;
        if (v[x]>rank) {
            ans=upper_bound(l[x],rank);
            if (ans==-1) ans=x;
        } else ans=upper_bound(r[x],rank);
        return ans;
    }
    void pri(int x){
        if (l[x]) pri(l[x]);
        cout<<v[x]<<' ';
        if (r[x]) pri(r[x]);
    }
    int get_rank(int x,ll val) {
        if (!x) return 0;
        if (v[x]==val) return size[l[x]]+1;
        else if (val<v[x]) return get_rank(l[x],val);
        else return get_rank(r[x],val)+size[l[x]]+w[x];
    }
    int how_many_number_lower_than_x(int x,ll val) {
        if (!x) return 0;
        if (v[x]==val) return size[l[x]];
        else if (val<v[x]) return how_many_number_lower_than_x(l[x],val);
        else return how_many_number_lower_than_x(r[x],val)+size[l[x]]+w[x];
    }
    int get_kth(int x,int k) {
        if (!x) return 0;
        if (k<=size[l[x]]) return get_kth(l[x],k);
        else if (k<=size[l[x]]+w[x]) return x;
        else return get_kth(r[x],k-size[l[x]]-w[x]);
    }
}T;

const int maxn =60000;
int root[maxn<<2];
ll a[maxn];
void build(int l,int r,int o) {
    Fork(i,l,r) T.insert(root[o],a[i]);
    if (l==r) {
        return ;
    }
    int m=(l+r)>>1;
    build(l,m,Lson),build(m+1,r,Rson);
}
void update(int l,int r,int o,int p,ll v) {
    T.del(root[o],a[p]);
    T.insert(root[o],v);
    if (l==r) {
        return;
    }
    int m=(l+r)>>1;
    if (p<=m) update(l,m,Lson,p,v); 
    else update(m+1,r,Rson,p,v);
}
ll tmp;
void query_lower_bound(int l,int r,int o,int L,int R,ll v) {
    if(L<=l && r<=R ) {int p=T.lower_bound(root[o],v); if (p!=-1) tmp=max(tmp,T.v[p]); return;}
    int m=(l+r)>>1;
    if(L<=m) query_lower_bound(l,m,Lson,L,R,v);
    if(m<R) query_lower_bound(m+1,r,Rson,L,R,v); 
}
void query_upper_bound(int l,int r,int o,int L,int R,ll v) {
    if(L<=l && r<=R ) {int p=T.upper_bound(root[o],v); if (p!=-1) tmp=min(tmp,T.v[p]); return;}
    int m=(l+r)>>1;
    if(L<=m) query_upper_bound(l,m,Lson,L,R,v);
    if(m<R) query_upper_bound(m+1,r,Rson,L,R,v); 
}
void query_rank(int l,int r,int o,int L,int R,ll v) {
    if(L<=l && r<=R ) {tmp+=T.how_many_number_lower_than_x(root[o],v); return;}
    int m=(l+r)>>1;
    if(L<=m) query_rank(l,m,Lson,L,R,v);
    if(m<R) query_rank(m+1,r,Rson,L,R,v); 
}
int query_kth(int L,int R,ll v) {
    int l=0,r=INF,ans;
    while(l<=r) {
        int m=(l+r)/2;
        tmp=0;query_rank(1,n,1,L,R,m);
        if (tmp<v) l=m+1,ans=m;else r=m-1;
    }
    return ans;
}
int main() {
    // freopen("bzoj3196.in","r",stdin);
    n=read();   m=read();
    For(i,n) a[i]=read();
    build(1,n,1);
    For(i,m) {
        int opt=read(),x=read(),y=read(); ll v;
        if (opt^3) v=read();
            // cout<<opt<<' '<<x<<' '<<y<<' '<<v<<endl;
        switch (opt) {
            case 1:tmp=1;query_rank(1,n,1,x,y,v);printf("%lld\n",tmp);break;
            case 2:tmp=1;printf("%d\n",query_kth(x,y,v));break;
            case 3:update(1,n,1,x,y);a[x]=y;break;
            case 4:tmp=-INF;query_lower_bound(1,n,1,x,y,v-1);printf("%lld\n",tmp);break;
            case 5:tmp=INF;query_upper_bound(1,n,1,x,y,v);printf("%lld\n",tmp);break;
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值