zoukankan      html  css  js  c++  java
  • 【模板】可持久化线段树[主席树]

    P3834 【模板】可持久化线段树 1(主席树)

    询问区间第k大 照着学长模板打的

    资料       

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+5,M=100000+5,inf=0x3f3f3f3f;
    int n,m,a[N],w[N];
    int tl,tot=0,rt[N];
    template<class t>void rd(t &x){
        x=0;int w=0;char ch=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=w?-x:x;
    }
    
    struct tree{
        int l,r,sum;
    }t[N*50];
    
    void pup(int o){
        t[o].sum=t[t[o].l].sum+t[t[o].r].sum;
    }
    void update(int l,int r,int &o,int pre,int k){
        o=++tot;
        if(l==r){t[o].sum=t[pre].sum+1;return;}
        int mid=l+r>>1;
        if(k<=mid) update(l,mid,t[o].l,t[pre].l,k),t[o].r=t[pre].r;
        else update(mid+1,r,t[o].r,t[pre].r,k),t[o].l=t[pre].l;
        pup(o);
    }
    
    int query(int l,int r,int x,int y,int k){
        if(l==r) return l;
        int mid=l+r>>1,ss=t[t[y].l].sum-t[t[x].l].sum;
        if(ss>=k) return query(l,mid,t[x].l,t[y].l,k);
        else return query(mid+1,r,t[x].r,t[y].r,k-ss);
    }
    
    int main(){
        rd(n),rd(m);
        for(int i=1;i<=n;++i) rd(a[i]),w[i]=a[i];
        sort(a+1,a+n+1);
        tl=unique(a+1,a+n+1)-a-1;
        for(int i=1;i<=n;++i){
            w[i]=lower_bound(a+1,a+tl+1,w[i])-a;
            update(1,tl,rt[i],rt[i-1],w[i]);
        }
        for(int i=1,l,r,k;i<=m;++i){
            rd(l),rd(r),rd(k);
            printf("%d
    ",a[query(1,tl,rt[l-1],rt[r],k)]);
        }
        return 0;
    } 

    QAQ居然和我看的那个版本不一样

    /*  主席树求区间第K大模板:
        模板特殊说明:
        每棵树是维护从1开始到cnt的下标信息
    */
     #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<algorithm>
    #define ll long long
    #define go(i,x,a) for(int i=a;i<x;i++)
    #define INF 0x7f7f7f7f
    using namespace std;
     
    const int maxn=1e5+5;
    int T,n,m,tot,a[maxn],b[maxn],cnt,roots[maxn];
    struct N { int ls, rs, w; } tree[30 * maxn];
     
    int build_tree(int l, int r) {  
        int newnode = tot++;
        tree[newnode].w = 0;
        if (l != r) {
            int mid = (l + r) / 2;
            tree[newnode].ls = build_tree(l, mid);
            tree[newnode].rs = build_tree(mid + 1, r);
        }
        return newnode;
    }
     
    int updata(int rt, int pos, int val) {  
        int newnode = tot++, tmp = newnode;
        tree[newnode].w = tree[rt].w + val;
        int l = 1, r = cnt;
        while (l < r) {
            int mid = (l + r) / 2;
            if (pos <= mid) {
                tree[newnode].ls = tot++;
                tree[newnode].rs = tree[rt].rs;
                newnode = tree[newnode].ls;
                rt = tree[rt].ls;
                r = mid;
            }
            else {
                tree[newnode].ls = tree[rt].ls;
                tree[newnode].rs = tot++;
                newnode = tree[newnode].rs;
                rt = tree[rt].rs;
                l = mid + 1;
            }
            tree[newnode].w = tree[rt].w + val;
        }
        return tmp;
    }
     
    int query(int rt1, int rt2, int k) {  
        int l = 1, r = cnt;
        while (l < r) {
            int mid = (l + r) / 2;
            int tmp = tree[tree[rt2].ls].w - tree[tree[rt1].ls].w;
            if (tmp >= k) {
                rt1 = tree[rt1].ls;
                rt2 = tree[rt2].ls;
                r = mid;
            }
            else {
                k -= tmp;
                rt1 = tree[rt1].rs;
                rt2 = tree[rt2].rs;
                l = mid + 1;
            }
        }
        return l;
    }
     
    int main() {
        scanf("%d", &T);
        while (T--) {  
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
                b[i - 1] = a[i];
            }
            sort(b, b + n);
            cnt = unique(b, b + n) - b;    
            tot = 0;
            roots[0] = build_tree(1, cnt);
            for (int i = 1; i <= n; i++) {
                int tmp = (int)(lower_bound(b, b + cnt, a[i]) - b) + 1;
                roots[i] = updata(roots[i - 1], tmp, 1);   
            }
            int l,r,k;
            for(int i=0;i<m;i++){
                scanf("%d %d %d",&l,&r,&k); 
                int tmp = query(roots[l-1],roots[r],k);
                printf("%d
    ",b[tmp - 1]);
            }
        }
        return 0;
    }//Faze
    学长’s
  • 相关阅读:
    day22 sys模块(☆☆☆)json & pickle模块(☆☆☆☆)
    day22 OS模块
    day21 time时间模块
    day21 if __name__==""__main__""的用法
    day21 模块
    day20 装饰器 (装饰器=高阶函数+函数嵌套+闭包)加上参数
    day19 生产者模型-next与send用法详解-生产者消费者模型
    day19 生成器函数的好处
    zzq's sort [思维题]
    三元组 [01Trie]
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/11278724.html
Copyright © 2011-2022 走看看