zoukankan      html  css  js  c++  java
  • 可持久化线段树(主席树)

    主席树留坑

    可持久化权值线段树:

    区间第k小数

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<cmath>
    #include<map>
    #include<bitset>
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define dwn(i,a,b) for(int i=(a);i>=(b);--i)
    using namespace std;
    typedef long long ll;
    const int N=200000;
    int n,m,cnt,tot=0;
    int a[N+10],b[N+10],rt[N+10];
    int sum[100*N+10],tl[100*N+10],tr[100*N+10];
    int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=(x<<3)+(x<<1)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    int build(int l,int r)
    {
        int t=++tot;
        sum[tot]=0;
        if(l<r)
        {
            int mid=(l+r)>>1;
            tl[t]=build(l,mid);
            tr[t]=build(mid+1,r);
        }
        return t;
    }
    int update(int pre,int l,int r,int x)
    {
        int t=++tot;
        tl[t]=tl[pre];tr[t]=tr[pre];sum[t]=sum[pre]+1;
        if(l<r)
        {
            int mid=(l+r)>>1;
            if(x<=mid) tl[t]=update(tl[pre],l,mid,x);
            else tr[t]=update(tr[pre],mid+1,r,x);
        }
        return t;
    }
    int ask_sum(int u,int v,int l,int r,int k)
    {
        if(l>=r) return l;
        int x=sum[tl[v]]-sum[tl[u]];
        int mid=(l+r)>>1;
        if(k<=x) return ask_sum(tl[u],tl[v],l,mid,k);
        else return ask_sum(tr[u],tr[v],mid+1,r,k-x);
    }
    int main()
    {
        n=read(),m=read();
        rep(i,1,n)
        {
            a[i]=b[i]=read();
        }
        sort(b+1,b+n+1);
        cnt=unique(b+1,b+n+1)-b-1;
        rt[0]=build(1,cnt);
        rep(i,1,n)
        {
            int t=lower_bound(b+1,b+cnt+1,a[i])-b;
            rt[i]=update(rt[i-1],1,cnt,t);
        }
        rep(i,1,m)
        {
            int l=read(),r=read(),k=read();
            printf("%d
    ",b[ask_sum(rt[l-1],rt[r],1,cnt,k)]);
        }
        return 0;
    }
    

    可持久化数组-线段树实现:

    可持久化数组

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<cmath>
    #include<map>
    #include<bitset>
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define dwn(i,a,b) for(int i=(a);i>=(b);--i)
    using namespace std;
    typedef long long ll;
    const int N=1000000;
    int n,m,a[N+10],rt[N+10],val[40*N+10],tl[40*N+10],tr[40*N+10],cnt=0,tot=0;
    int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=(x<<3)+(x<<1)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    int build(int l,int r)
    {
        int t=++tot;
        if(l==r)
        {
            val[t]=a[l];
            return t;
        }
        int mid=(l+r)>>1;
        tl[t]=build(l,mid);
        tr[t]=build(mid+1,r);
        return t;
    }
    int update(int pre,int l,int r,int x,int d)
    {
        int t=++tot;
        if(l==r)
        {
            val[t]=d;
            return t;
        }
        tl[t]=tl[pre],tr[t]=tr[pre];
        int mid=(l+r)>>1;
        if(x<=mid) tl[t]=update(tl[pre],l,mid,x,d);
        else tr[t]=update(tr[pre],mid+1,r,x,d);
        return t;
    }
    int ask_val(int t,int l,int r,int x)
    {
        if(l==r) return val[t];
        int mid=(l+r)>>1;
        if(x<=mid) return ask_val(tl[t],l,mid,x);
        else return ask_val(tr[t],mid+1,r,x);
    }
    int main()
    {
        n=read(),m=read();
        rep(i,1,n) a[i]=read();
        rt[0]=build(1,n);
        rep(i,1,m)
        {
            int t=read(),opt=read(),x=read();
            if(opt==1) {int d=read();rt[++cnt]=update(rt[t],1,n,x,d);}
            if(opt==2) {printf("%d
    ",ask_val(rt[t],1,n,x));rt[++cnt]=rt[t];}
        }
        return 0;
    }
    
  • 相关阅读:
    获取到某一方法的调用者的类名、方法名、命名空间(转)
    JQ插件收集
    输出KnownColor枚举颜色值
    SQL 优化之该走索引却不走索引的分析
    oracle日期处理(一)
    ORACLE如何使用DBMS_METADATA.GET_DDL获取DDL语句
    案例分析:ora04031与ora04030错误分析与解决
    分区表、分区索引和全局索引部分总结
    Oracle性能调整指导纲要
    ORACLE常用SQL优化hint语句
  • 原文地址:https://www.cnblogs.com/MYsBlogs/p/11379844.html
Copyright © 2011-2022 走看看