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;
    }
  • 相关阅读:
    hibernate对应关系详解(转)
    mybatis genertor两种使用方式(文件+项目)
    YII2 union 不同数据结构时 解决方案
    Yii2 分表后 使用 union all 分页实现代码
    Beyond Compare 4.2.10手动破解
    Xshell 6+Xftp 6官方下载免费版
    Navicat Premium
    yii2的Console定时任务创建
    内嵌多个youtube视频并展现该频道所有视频列表
    video.js 动态获取URL 并播放youtube视频
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13418802.html
Copyright © 2011-2022 走看看