P3380 二逼平衡树(带修改区间第K大+平衡树的基本操作)(线段树套Treap树)

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

  1. 查询k在区间内的排名

  2. 查询区间内排名为k的值

  3. 修改某一位值上的数值

  4. 查询k在区间内的前驱(前驱定义为严格小于x,且最大的数,若不存在输出-2147483647)

  5. 查询k在区间内的后继(后继定义为严格大于x,且最小的数,若不存在输出2147483647)

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
const int inf=2147483647;
int n,m;
int a[maxn];

struct Treap_tree {
    int ch[2];
    int v;
    int dat;//优先级 
    int size;//子树节点数 
    int cnt;//重复数 
}t[maxn*10];
int tot;
int root;
int newNode (int v) {
    tot++;
    t[tot].v=v;
    t[tot].dat=rand();//随机优先级
    t[tot].size=1;
    t[tot].cnt=1;
    return tot; 
} 
void pushup (int x) {
    t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt;
}
void build () {
    root=newNode(-inf);
    t[root].ch[1]=newNode(inf);
    pushup(root);
}
void rotate (int &id,int d) {
    int tt=t[id].ch[d^1];
    t[id].ch[d^1]=t[tt].ch[d];
    t[tt].ch[d]=id;
    id=tt;
    pushup(t[id].ch[d]);
    pushup(id);
}
void ins (int &id,int v) {
    if (!id) {
        id=newNode(v);
        return;
    }
    if (v==t[id].v) t[id].cnt++;
    else {
        ins(t[id].ch[v>t[id].v],v);
        if (t[id].dat<t[t[id].ch[v>t[id].v]].dat) rotate(id,v<t[id].v);
    }
    pushup(id);
}
void remove (int &id,int v) {
    if (!id) return;
    if (v==t[id].v) {
        if (t[id].cnt>1) {
            t[id].cnt--;
            pushup(id);
            return;
        }
        if (t[id].ch[0]||t[id].ch[1]) {
            if (!t[id].ch[1]||t[t[id].ch[0]].dat>t[t[id].ch[1]].dat) {
                rotate(id,1);
                remove(t[id].ch[1],v);
            }
            else {
                rotate(id,0);
                remove(t[id].ch[0],v);
            }
            pushup(id);
        }
        else
            id=0;
        return;
    }
    remove(t[id].ch[v>t[id].v],v);
    pushup(id);
}
int rk (int id,int v) {
    if (!id) return 0;
    if (v==t[id].v) 
        return t[t[id].ch[0]].size;
    else if (v<t[id].v)
        return rk(t[id].ch[0],v);
    else
        return t[t[id].ch[0]].size+t[id].cnt+rk(t[id].ch[1],v);
}
int kth (int id,int k) {
    if (!id) return inf;
    if (k<=t[t[id].ch[0]].size)
        return kth(t[id].ch[0],k);
    else if (k<=t[t[id].ch[0]].size+t[id].cnt)
        return t[id].v;
    else
        return kth(t[id].ch[1],k-t[t[id].ch[0]].size-t[id].cnt);
}
int get_pre (int id,int v) {
    if (!id)
        return -inf;
    if (t[id].v>=v)
        return get_pre(t[id].ch[0],v);
    else
        return max(t[id].v,get_pre(t[id].ch[1],v));
}
int get_next (int id,int v) {
    if (!id)
        return inf;
    if (t[id].v<=v)
        return get_next(t[id].ch[1],v);
    else
        return min(t[id].v,get_next(t[id].ch[0],v));
}




struct node {
    int l,r,root;
}segTree[maxn*3];
void seg_build (int i,int l,int r) {
    segTree[i].l=l;
    segTree[i].r=r;
    for (int p=l;p<=r;p++) ins(segTree[i].root,a[p]);
    if (l==r) return;
    int mid=(l+r)>>1;
    seg_build(i<<1,l,mid);
    seg_build(i<<1|1,mid+1,r);
}
void modify (int i,int x,int y) {
    remove(segTree[i].root,a[x]);
    ins(segTree[i].root,y);
    if (segTree[i].l==segTree[i].r) return;
    int mid=(segTree[i].l+segTree[i].r)>>1;
    if (x>mid)
        modify(i<<1|1,x,y);
    else
        modify(i<<1,x,y);
}
int query_rank (int i,int l,int r,int k) {
    //查询某数的排名 
    if (segTree[i].l>r||segTree[i].r<l) return 0;
    if (segTree[i].l>=l&&segTree[i].r<=r)
        return rk(segTree[i].root,k);
    else
        return query_rank(i<<1,l,r,k)+query_rank(i<<1|1,l,r,k);
}
int query_kth (int u,int v,int k) {
    //查询区间第k大
    int l=0,r=1e8;
    while (l<=r) {
        int mid=(l+r)>>1;
        if (query_rank(1,u,v,mid)<k)
            l=mid+1;
        else
            r=mid-1;
    } 
    return r;
}
int query_pre (int i,int l,int r,int k) {
    //查询区间前驱
    if (segTree[i].l>r||segTree[i].r<l)
        return -2147483647;
    if (segTree[i].l>=l&&segTree[i].r<=r)
        return get_pre(segTree[i].root,k);
    else 
        return max(query_pre(i<<1,l,r,k),query_pre(i<<1|1,l,r,k)); 
}
int query_nxt (int i,int l,int r,int k) {
    if (segTree[i].l>r||segTree[i].r<l)
        return 2147483647;
    if (segTree[i].l>=l&&segTree[i].r<=r)
        return get_next(segTree[i].root,k);
    else
        return min(query_nxt(i<<1,l,r,k),query_nxt(i<<1|1,l,r,k));
}
int main () {
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d",a+i);
    seg_build(1,1,n);
    for (int i=0;i<m;i++) {
        int op;
        scanf("%d",&op);
        if (op==1) {
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",query_rank(1,l,r,k)+1);
        }
        if (op==2) {
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",query_kth(l,r,k));
        }
        if (op==3) {
            int x,y;
            scanf("%d%d",&x,&y);
            modify(1,x,y);
            a[x]=y;
        }
        if (op==4) {
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",query_pre(1,l,r,k));
        }
        if (op==5) {
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",query_nxt(1,l,r,k));
        }
    }
    return 0;
}

 

posted @ 2020-08-02 15:01  zlc0405  阅读(165)  评论(0编辑  收藏  举报