数据结构——主席树

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\n",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\n",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\n",ans);
        last = ans;
    }
    return 0;
}
posted @ 2020-09-04 13:36  wsl_lld  阅读(183)  评论(0编辑  收藏  举报