• 主席树学习


    求区间第k小

    题目链接:https://www.luogu.org/problem/P3834

    #include<bits/stdc++.h>
    
    #define ll long long
    #define ull unsigned long long
    #define met(a, x) memset(a,x,sizeof(a))
    #define inf 0x3f3f3f3f
    #define Rint register int
    
    using namespace std;
    const ll mod = 1e9 + 7;
    const int N = 2e5 + 10;
    const int M = 3e6 + 10;
    int a[N], b[N], c[N], cnt;
    int sum[N << 5], L[N << 5], R[N << 5];
    
    inline int build(int l, int r) {
        int rt = ++cnt;
        sum[rt] = 0;
        if (l < r) {
            int mid = (l + r) / 2;
            L[rt] = build(l, mid);
            R[rt] = build(mid + 1, r);
        }
        return rt;
    }
    
    inline int update(int pre, int l, int r, int x) {
        int rt = ++cnt;
        L[rt] = L[pre], R[rt] = R[pre], sum[rt] = sum[pre] + 1;
        if (l < r) {
            int mid = (l + r) / 2;
            if (x <= mid)L[rt] = update(L[pre], l, mid, x);
            else R[rt] = update(R[pre], mid + 1, r, x);
        }
        return rt;
    }
    
    inline int query(int u, int v, int l, int r, int k) {
        if (l >= r)return l;
        int x = sum[L[v]] - sum[L[u]];
        int mid = (l + r) / 2;
        if (x >= k)return query(L[u], L[v], l, mid, k);
        else return query(R[u], R[v], mid + 1, r, k - x);
    }
    
    int main() {
       // freopen("in","r",stdin);
    //    freopen("out","w",stdout);
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            b[i] = a[i];
        }
        sort(b + 1, b + 1 + n);
        int len = unique(b + 1, b + 1 + n) - (b + 1);
        c[0] = build(1, len);
        for (int i = 1; i <= n; i++) {
            int t = lower_bound(b + 1, b + 1 + len, a[i]) - b;
            c[i] = update(c[i - 1], 1, len, t);
        }
        while (m--) {
            int x, y, z;
            cin >> x >> y >> z;
            int t = query(c[x - 1], c[y], 1, len, z);
            cout << b[t] << endl;
        }
        return 0;
    }

    动态主席树,求区间第k小

    题目链接:https://www.luogu.org/problem/P2617

    可持久化数组

    题目链接:https://www.luogu.org/problem/P3919

    #include<bits/stdc++.h>
    #define mid ((l+r)>>1)
    using namespace std;
    int rt[1000001],T[20000001],L[20000001],R[20000001];
    int cnt;
    int build(int l,int r)
    {
        int root=++cnt;
        if(l==r)
        {
            scanf("%d",&T[root]);
            return root;
        }
        L[root]=build(l,mid);
        R[root]=build(mid+1,r);
        return root;
    }
    int update(int pre,int l,int r,int x,int c)
    {
        int root=++cnt;
        if(l==r)
        {
            T[root]=c;
            return root;
        }
        L[root]=L[pre];
        R[root]=R[pre];
        if(x<=mid)L[root]=update(L[pre],l,mid,x,c);
        else R[root]=update(R[pre],mid+1,r,x,c);
        return root;
    }
    void query(int pre,int l,int r,int x)
    {
        if(l==r)
        {
            printf("%d
    ",T[pre]);
            return;
        }
        if(x<=mid)query(L[pre],l,mid,x);
        else query(R[pre],mid+1,r,x);
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        int v,cd,x,y;
        rt[0]= build(1,n);
        for(int i=1; i<=m; ++i)
        {
            scanf("%d%d%d",&v,&cd,&x);
            if(cd==1)
            {
                scanf("%d",&y);
                rt[i]= update( rt[v],1,n,x,y);
            }
            if(cd==2)
            {
                rt[i]= rt[v];
                query( rt[v],1,n,x);
            }
        }
        return 0;
    }
  • 相关阅读:
    centos配置ADSL拨号 配置阿里云的yum源
    强烈推荐:一个网页转安卓App的工具,可以在线云打包apk
    【html5】input标签capture属性不为人知的秘密
    国庆微信头像在线生成器,头像加国旗小工具
    这是一个玩法简单又充满刺激的安卓App游戏
    微信群二维码突破100人限制和7天不过期的方法
    Xcode9学习笔记84
    Xcode9学习笔记83
    Xcode9学习笔记80
    python 压缩文件.zip
  • 原文地址:https://www.cnblogs.com/nublity/p/11421016.html
Copyright © 2020-2023  润新知