zoukankan      html  css  js  c++  java
  • 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
    ",query_rank(1,l,r,k)+1);
            }
            if (op==2) {
                int l,r,k;
                scanf("%d%d%d",&l,&r,&k);
                printf("%d
    ",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
    ",query_pre(1,l,r,k));
            }
            if (op==5) {
                int l,r,k;
                scanf("%d%d%d",&l,&r,&k);
                printf("%d
    ",query_nxt(1,l,r,k));
            }
        }
        return 0;
    }
  • 相关阅读:
    1063. Set Similarity
    A1047. Student List for Course
    A1039. Course List for Student
    最大公约数、素数、分数运算、超长整数计算总结
    A1024. Palindromic Number
    A1023. Have Fun with Numbers
    A1059. Prime Factors
    A1096. Consecutive Factors
    A1078. Hashing
    A1015. Reversible Primes
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13418802.html
Copyright © 2011-2022 走看看