zoukankan      html  css  js  c++  java
  • 数据结构——主席树

    1.P3919 【模板】可持久化线段树 1(可持久化数组)

    点击查看代码块
    #include <bits/stdc++.h>
    
    #define mkp make_pair
    #define pb push_back
    #define v(T) vector<T>
    #define all(x) x.bg,x.ed
    #define newline puts("")
    #define si(x) ((int)x.size())
    #define rep(i,n) for(int i=1;i<=n;++i)
    #define rrep(i,n) for(int i=0;i<n;++i)
    #define srep(i,s,t) for(int i=s;i<=t;++i)
    
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    const int maxn = 1e6+10;
    const int inf = 0x7f7f7f7f;
    const ll inf_ll = 1ll*inf*inf;
    const int Mod = 1e9+7;
    const double eps = 1e-7;
    int T[maxn<<5];//存储历史版本
    int tree[maxn<<5],lc[maxn<<5],rc[maxn<<5];
    int n,q;
    int a[maxn];
    int tot = 0;
    
    int build(int l,int r){
        int rt=++tot;
        if(l==r){
            tree[rt]=a[l];
            return rt;
        }
        int m=(l+r)>>1;
        lc[rt]=build(l,m);
        rc[rt]=build(m+1,r);
        return rt;
    }
    
    int update(int pre,int x,int val,int l,int r){
        int rt=++tot;
        if(l==r){
            tree[rt]=val;
            return rt;
        }
        lc[rt]=lc[pre],rc[rt]=rc[pre];
        int m=(l+r)>>1;
        if(x<=m) lc[rt]=update(lc[pre],x,val,l,m);
        else rc[rt]=update(rc[pre],x,val,m+1,r);
        return rt;
    }
    
    int query(int pre,int x,int l,int r){
        if(l==r){
            return tree[pre];
        }
        int m=(l+r)>>1;
        if(x<=m) return query(lc[pre],x,l,m);
        else return query(rc[pre],x,m+1,r);
    }
    
    int main(){
        cin>>n>>q;
        for (int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }    
        T[0]=build(1,n);
        for (int i=1;i<=q;i++){
            int v,op;//历史版本,操作
            scanf("%d%d",&v,&op);
            if(op == 1){
                int x,y;
                scanf("%d%d",&x,&y);
                T[i]=update(T[v],x,y,1,n);
            }
            else if(op == 2){
                int x;
                scanf("%d",&x);
                T[i]=T[v];
                int ans = query(T[v],x,1,n);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    

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

    点击查看代码块
    #include <bits/stdc++.h>
    
    #define mkp make_pair
    #define pb push_back
    #define v(T) vector<T>
    #define all(x) x.bg,x.ed
    #define newline puts("")
    #define si(x) ((int)x.size())
    #define rep(i,n) for(int i=1;i<=n;++i)
    #define rrep(i,n) for(int i=0;i<n;++i)
    #define srep(i,s,t) for(int i=s;i<=t;++i)
    
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    const int maxn = 2e5+10;
    const int inf = 0x7f7f7f7f;
    const ll inf_ll = 1ll*inf*inf;
    const int Mod = 1e9+7;
    const double eps = 1e-7;
    
    int n,m;
    ll tree[maxn<<5],lc[maxn<<5],rc[maxn<<5];
    ll T[maxn];
    ll tot = 0;//当前节点编号
    ll a[maxn],b[maxn];//a原数组,b离散化数组
    
    int build(int l,int r){
        int rt = ++tot;
        tree[rt] = 0;
        if(l==r){
            return rt;
        }
        int m=(l+r)>>1;
        lc[rt]=build(l,m);
        rc[rt]=build(m+1,r);
        return rt;
    }
    
    int update(int pre,int x,int l,int r){
        int rt = ++tot;
        if(l == r){
            tree[rt]=tree[pre]+1;
            return rt;
        }
        lc[rt]=lc[pre];rc[rt]=rc[pre];tree[rt]=tree[pre]+1;
        int m=(l+r)>>1;
        if(x<=m) lc[rt]=update(lc[pre],x,l,m);
        else rc[rt]=update(rc[pre],x,m+1,r);
        return rt;
    }
    
    int query(int u,int v,int l,int r,int k){
        if(l==r) return l;
        int x=tree[lc[v]]-tree[lc[u]];//前缀值相减
    
        int m=(l+r)>>1;
        if(x>=k) return query(lc[u],lc[v],l,m,k);
        else return query(rc[u],rc[v],m+1,r,k-x);//注意这里的k变为k-x
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            b[i]=a[i];
        }
        sort(b+1,b+n+1);
        int cnt = unique(b+1,b+n+1)-b-1;
        T[0] = build(1,cnt);
        for (int i=1;i<=n;i++){
            int pos = lower_bound(b+1,b+cnt+1,a[i])-b;
            T[i]=update(T[i-1],pos,1,cnt);
        }
        while(m--){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            int pos = query(T[x-1],T[y],1,cnt,z);
            printf("%lld
    ",b[pos]);
        }
        return 0;
    }
    

    3.P2633 Count on a tree

    主席树+树上差分

    点击查看代码块
    #include <bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> pii;
    typedef long long ll;
    
    const int maxn = 1e5+10;
    int n,m;
    int a[maxn],b[maxn];
    vector<int> G[maxn];
    int fa[maxn][35];
    int dep[maxn];
    int tot;//离散化
    void dfs(int u,int f){
        dep[u] = dep[f] + 1;
        fa[u][0] = f;
        for (int i=1;(1<<i)<=dep[u];i++){
            fa[u][i] = fa[fa[u][i-1]][i-1];
        }
        for (auto v : G[u]){
            if( v==f ) continue;
            dfs(v,u);
        }
    }
    
    int lca(int u,int v){
        if(dep[u]<dep[v]) swap(u,v);
        for (int i=30;i>=0;i--){
            int d = dep[u]-dep[v];
            if(d>=(1<<i)) u = fa[u][i];
        }
        if(u==v) return u;
        for (int i=30;i>=0;i--){
            if(fa[u][i]!=fa[v][i]){
                u = fa[u][i];
                v = fa[v][i];
            }
        }
        return fa[u][0];
    }
    
    
    int id[maxn],cnt = 0;
    int num[maxn<<5],lc[maxn<<5],rc[maxn<<5];
    void pushup(int p){
        num[p] = num[lc[p]] + num[rc[p]];
    }
    
    int update(int pre,int l,int r,int pos,int val){
        int p = ++cnt;
        lc[p]=lc[pre],rc[p]=rc[pre],num[p]=num[pre];
        if(l == r){
            num[p]+=val;
            return p;
        }
        int m = (l+r)>>1;
        if(pos <= m) lc[p]=update(lc[pre],l,m,pos,val);
        else rc[p]=update(rc[pre],m+1,r,pos,val);
        pushup(p);
        return p;
    }
    
    int query(int aa,int bb,int cc,int dd,int l,int r,int k){
        if(l == r) return b[l];
        int x = num[lc[aa]]+num[lc[bb]]-num[lc[cc]]-num[lc[dd]];
        int m = (l+r)>>1;
        if(x >= k) return query(lc[aa],lc[bb],lc[cc],lc[dd],l,m,k);
        else return query(rc[aa],rc[bb],rc[cc],rc[dd],m+1,r,k-x);
    }
    
    void dfs2(int u,int f){
        int pos = lower_bound(b+1,b+tot+1,a[u])-b;
        id[u] = update(id[f],1,tot,pos,1);
        for (auto v : G[u]){
            if(v == f) continue;
            dfs2(v,u);
        }
    }
    int main(){
        cin>>n>>m;
        for (int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            b[i] = a[i];
        }
        sort(b+1,b+n+1);
        tot = unique(b+1,b+n+1)-b-1;
    
        for (int i=1;i<n;i++){
            int u,v;scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
    
        dfs(1,0);
        dfs2(1,0);
        int last = 0;
        for (int i=1;i<=m;i++){
            int u,v,k;
            scanf("%d%d%d",&u,&v,&k);
            u^=last;
            int Lca = lca(u,v),f = fa[Lca][0];
            int ans = query(id[u],id[v],id[Lca],id[f],1,tot,k);
            printf("%d
    ",ans);
            last = ans;
        }
        return 0;
    }
    
    你将不再是道具,而是成为人如其名的人
  • 相关阅读:
    关于read函数的一些分析
    条件变量
    epoll的边缘触发与水平触发
    内核态的接收缓冲区和发送缓冲区
    SourceTreet提交时显示remote: Incorrect username or password ( access token )(4种解决办法)
    前端技术汇总+Vue最新快速上手
    MyBatisPlus性能分析插件,条件构造器,代码自动生成器详解
    博客园怎样在Markdown编辑模式下调整图片大小(已解决)
    MyBatisPlus分页查询,删除操作
    idea括号选中时出现一条下滑线(突出显示)打开或关闭方法
  • 原文地址:https://www.cnblogs.com/wsl-lld/p/13613337.html
Copyright © 2011-2022 走看看