P2633 Count on a tree
题意:
给定一棵 n 个节点的树,每个点有一个权值。有 m 个询问,每次给你 u,v,k,你需要回答 u xor last 和 v 这两个节点间第 k 小的点权。
其中last 是上一个询问的答案,定义其初始为 0,即第一个询问的 u 是明文。
题解:
很明显,主席树,而且强制在线(更是主席树)
主席树是维护了一个类似前缀和的数据结构,当要查询线性区间[l,r]的第k小时,用第r个线段树减第l-1个线段树,得到的就是[l,r]之间的权值线段树(因为主席树维护的就是前缀和),然后直接用二分查找第k小就行
在本题中给了一个树,问点u到点v之间的第k小,我们都知道树上差分(应该都知道),我们利用树上差分就可以得到u到v之间的数据
定义s[u]为从根节点到点u节点的主席树,那么u到v之间的所有数值信息的主席树就应该是:
s[u]+s[v]-s[lca[u,v]]-s[fa[lca(u,v)]]
因为需要lca所以要用到倍增,可以在dfs中插入每个点
代码:
#include<bits/stdc++.h>
using namespace std;
#define N 100010
#define M 2000010
int read(){int ans=0,w=1;char c=getchar();while(c!='-'&&!isdigit(c))c=getchar();if(c=='-')w=-1,c=getchar();while(isdigit(c))ans=ans*10+c-'0',c=getchar();return ans*w;
}
int n,m,num,lastans=0,u,v,tot,cnt;
struct Edge{int v,next;}E[N<<1];
int head[N],a[N],b[N],fa[N][32],dep[N];
int rt[M]={0},ls[M]={0},rs[M]={0},siz[M]={0};
void add(int u,int v){E[++tot]=(Edge){v,head[u]};head[u]=tot;
}
void modify(int &rt,int lastrt,int l,int r,int val){rt=++cnt;ls[rt]=ls[lastrt]; rs[rt]=rs[lastrt];siz[rt]=siz[lastrt]+1;if(l==r)return;int mid=l+r>>1;if(mid>=val)modify(ls[rt],ls[lastrt],l,mid,val);else modify(rs[rt],rs[lastrt],mid+1,r,val);
}
int query(int rt1,int rt2,int rt3,int rt4,int l,int r,int k){if(l==r)return l;int mid=(l+r)>>1;int tmp=siz[ls[rt1]]+siz[ls[rt2]]-siz[ls[rt3]]-siz[ls[rt4]];if(tmp>=k)return query(ls[rt1],ls[rt2],ls[rt3],ls[rt4],l,mid,k);else return query(rs[rt1],rs[rt2],rs[rt3],rs[rt4],mid+1,r,k-tmp);
}
void dfs(int u,int f){dep[u]=dep[f]+1;for(int i=head[u];i;i=E[i].next){int v=E[i].v;if(v==fa[u][0])continue;fa[v][0]=u;modify(rt[v],rt[u],1,num,a[v]);dfs(v,u);}
}
int Lca(int x,int y){if(dep[x]<dep[y])swap(x,y);int t=dep[x]-dep[y];for(int i=0;(1<<i)<=t;i++)if((1<<i)&t)x=fa[x][i];for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];if(x==y)return x;return fa[x][0];
}
int main(){n=read();m=read();for(int i=1;i<=n;i++)b[i]=a[i]=read();sort(b+1,b+n+1);num=unique(b+1,b+n+1)-b;for(int i=1;i<n;i++){u=read();v=read();add(u,v);add(v,u);}for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+num+1,a[i])-b;modify(rt[1],rt[0],1,num,a[1]);dfs(1,0);int up=log2(n);for(int k=1;k<=up;k++)for(int i=1;i<=n;i++)fa[i][k]=fa[fa[i][k-1]][k-1];for(int i=1;i<=m;i++){u=read();v=read();int k=read();u^=lastans;int lca=Lca(u,v);int ans=b[query(rt[u],rt[v],rt[lca],rt[fa[lca][0]],1,num,k)];printf("%d\n",ans);lastans=ans;}return 0;
}