洛谷 P2633 Count on a tree

->题目链接

题解:

主席树,可持久化,最近公共祖先,LCA,线段树

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100001 
using namespace std;
int n,m,tot,cnt,num,lastans;
int a[MAXN],ha[MAXN],root[MAXN],to[MAXN*2],net[MAXN*2],head[MAXN*2],top[MAXN],dad[MAXN],deep[MAXN],size[MAXN];
struct node{
    int l,r,cnt;
}tree[MAXN*20];
void add(int u,int v){
    to[++tot]=v;net[tot]=head[u];head[u]=tot;
    to[++tot]=u;net[tot]=head[v];head[v]=tot;
}
void insert(int pre,int &now,int l,int r,int k){
    tree[now=++num].cnt=tree[pre].cnt+1;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(k<=mid){
        tree[now].r=tree[pre].r;
        insert(tree[pre].l,tree[now].l,l,mid,k);
    }
    else{
        tree[now].l=tree[pre].l;
        insert(tree[pre].r,tree[now].r,mid+1,r,k);
    }
}
int query(int x,int y,int LCA,int fa_LCA,int l,int r,int k){
    if(l==r) return a[l];
    int mid=(l+r)>>1;
    int tmp=tree[tree[x].l].cnt+tree[tree[y].l].cnt-tree[tree[LCA].l].cnt-tree[tree[fa_LCA].l].cnt;
    if(k<=tmp) query(tree[x].l,tree[y].l,tree[LCA].l,tree[fa_LCA].l,l,mid,k);
    else query(tree[x].r,tree[y].r,tree[LCA].r,tree[fa_LCA].r,mid+1,r,k-tmp);
}
void dfs(int now){
    size[now]=1;
    insert(root[dad[now]],root[now],1,cnt,ha[now]);
    deep[now]=deep[dad[now]]+1;
    for(int i=head[now];i;i=net[i])
        if(dad[now]!=to[i]){
            dad[to[i]]=now;
            dfs(to[i]);
            size[now]+=size[to[i]];
        } 
}
void dfs1(int x){
    int t=0;
    if(top[x]==0) top[x]=x;
    for(int i=head[x];i;i=net[i])
        if(dad[x]!=to[i]&&size[to[i]]>size[t]) t=to[i];
    if(t){
        top[t]=top[x];dfs1(t);
    }
    for(int i=head[x];i;i=net[i])
        if(dad[x]!=to[i]&&t!=to[i]) dfs1(to[i]);
}
int lca(int x,int y){
    for(;top[x]!=top[y];){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        x=dad[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    return x;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),ha[i]=a[i];
    for(int i=1,u,v;i<n;i++)
        scanf("%d%d",&u,&v),add(u,v);
    sort(a+1,a+n+1);
    cnt=unique(a+1,a+1+n)-a-1;
    for(int i=1;i<=n;i++)
        ha[i]=lower_bound(a+1,a+1+cnt,ha[i])-a;
    dfs(1);
    dfs1(1);
    for(int i=1,u,k,v;i<=m;i++){
        scanf("%d%d%d",&u,&v,&k);
        u^=lastans;
        int LCA=lca(u,v);
        lastans=query(root[u],root[v],root[LCA],root[dad[LCA]],1,cnt,k);
        if(i!=m) cout<<lastans<<"
";
        else cout<<lastans;
    }
    return 0;
}
AC

给你个可以令你终生受益的建议。

啊?

和我在一起。

原文地址:https://www.cnblogs.com/GTBD/p/9435808.html