Count on a Tree
这次主席树要维护的是树上信息啦。
其实主席树基本的思想还是用前缀和,那么我们就仿照一下,在树上做前缀和就好啦。我们令第\(i\)个节点所在的主席树维护该点到根节点路径上的所有数(值域是数的值),之后在计算的时候,以\(v[p] + v[q] - v[lca(p,q)] - v[fa[lca(p,q)]]\)为标准来判定往哪边二分就可以了。
直接在\(dfs\)的时候建树即可,我使用\(ST\)表求\(lca\),其他的也无所谓。这题还是很好写的。
看一下代码。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
#define fr friend inline
#define y1 poj
#define mp make_pair
#define pr pair<int,int>
#define fi first
#define sc second
#define pb push_back
using namespace std;
typedef long long ll;
const int M = 200005;
const int N = 1000005;
const int INF = 1000000009;
const double eps = 1e-7;
int read()
{
int ans = 0,op = 1;char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
return ans * op;
}
struct node
{
int ls,rs,v;
}t[N<<3];
struct edge
{
int next,to;
}e[M<<1];
int a[M],b[M],n,m,root[M<<1],la,x,y,z,head[M],ecnt,dep[M],dfn[M<<1],pos[M],idx,lg[M<<1];
int st[22][M<<1],cnt,fat[M<<1],tot;
void add(int x,int y)
{
e[++ecnt].to = y;
e[ecnt].next = head[x];
head[x] = ecnt;
}
void modify(int old,int &p,int l,int r,int pos)
{
p = ++cnt;
t[p].ls = t[old].ls,t[p].rs = t[old].rs,t[p].v = t[old].v + 1;
if(l == r) return;
int mid = (l+r) >> 1;
if(pos <= mid) modify(t[old].ls,t[p].ls,l,mid,pos);
else modify(t[old].rs,t[p].rs,mid+1,r,pos);
}
int query(int p,int q,int f,int g,int l,int r,int k)
{
if(l == r) return l;
int mid = (l+r) >> 1;
int sum = t[t[p].ls].v + t[t[q].ls].v - t[t[f].ls].v - t[t[g].ls].v;
if(k <= sum) return query(t[p].ls,t[q].ls,t[f].ls,t[g].ls,l,mid,k);
else return query(t[p].rs,t[q].rs,t[f].rs,t[g].rs,mid+1,r,k - sum);
}
int Min(int p,int q)
{
return (dep[p] < dep[q]) ? p : q;
}
void dfs(int x,int fa)
{
dep[x] = dep[fa] + 1,dfn[++idx] = x,pos[x] = idx,fat[x] = fa;
modify(root[fa],root[x],1,tot,a[x]);
for(int i = head[x];i;i = e[i].next)
{
if(e[i].to != fa) dfs(e[i].to,x);
dfn[++idx] = x;
}
}
void build()
{
lg[0] = -1;
rep(i,1,idx) st[0][i] = dfn[i];
rep(i,1,idx) lg[i] = lg[i>>1] + 1;
rep(j,1,lg[idx])
rep(i,1,idx)
{
if(i + (1 << j) - 1 > idx) break;
st[j][i] = Min(st[j-1][i],st[j-1][i + (1 << (j-1))]);
}
}
int lca(int x,int y)
{
int kl = pos[x],kr = pos[y];
if(kl > kr) swap(kl,kr);
int k = lg[kr - kl + 1];
return Min(st[k][kl],st[k][kr - (1 << k) + 1]);
}
int main()
{
n = read(),m = read();
rep(i,1,n) a[i] = b[i] = read();
sort(b+1,b+1+n);
tot = unique(b+1,b+1+n) - b - 1;
rep(i,1,n) a[i] = lower_bound(b+1,b+1+tot,a[i]) - b;
rep(i,1,n-1) x = read(),y = read(),add(x,y),add(y,x);
dfs(1,0),build();
rep(i,1,m)
{
x = read(),y = read(),z = read();
x ^= la;
int g = lca(x,y),f = fat[g];
//printf("#%d %d %d %d\n",x,y,g,f);
int now = query(root[x],root[y],root[f],root[g],1,tot,z);
//printf("$%d\n",now);
la = b[now];
printf("%d\n",la);
}
return 0;
}
当你意识到,每个上一秒都成为永恒。