题目描述
点分治
询问拆成四条到根的询问。
bfs一遍,处理出可持久化点分树。
查询直接查。
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=400000+10,maxtot=maxn*30;
int son[maxn],sx[maxn],fa[maxn];
int rot[maxn],tree[maxtot][4];
ll d1[maxn*20],d2[maxn*20];
int s1[maxn*20],s2[maxn*20];
int h[maxn],go[maxn*2],dis[maxn*2],next[maxn*2],p[maxn],bb[maxn],cc[maxn],zs[maxn];
ll d[maxn][20];
int belong[maxn][20],f[maxn][20],dep[maxn],zjy[maxn],sta[80];
int size[maxn],a[maxn];
int h2[maxn*2],g2[maxn*4],di2[maxn*4],n2[maxn*4];
int ask[maxn];
ll sum[maxn];
bool bz[maxn];
int i,j,k,l,r,t,nn,n,m,tot,top,cnt,num,czy;
ll ans;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void add(int x,int y,int z){
go[++tot]=y;
dis[tot]=z;
next[tot]=h[x];
h[x]=tot;
}
void add2(int x,int y,int z){
g2[++num]=y;
di2[num]=z;
n2[num]=h2[x];
h2[x]=num;
}
void link(int x,int y,int z){
add2(x,y,z);
add2(y,x,z);
}
void new_build(int x,int y){
int t=h[x];
int i,j,k=0;
while (t){
if (go[t]!=y) bb[++k]=go[t],cc[k]=dis[t];
t=next[t];
}
if (k<=1){
fo(i,1,k) link(x,bb[i],cc[i]);
}
else{
fo(i,1,1) link(x,bb[i],cc[i]);
j=x;
fo(i,2,k){
++n;
zs[n]=x;
link(j,n,0);
j=n;
link(j,bb[i],cc[i]);
}
}
t=h[x];
while (t){
if (go[t]!=y) new_build(go[t],x);
t=next[t];
}
}
void dfs(int x,int y){
f[x][0]=y;
dep[x]=dep[y]+1;
int t=h[x];
while (t){
if (go[t]!=y) dfs(go[t],x);
t=next[t];
}
}
int lca(int x,int y){
if (dep[x]<dep[y]) swap(x,y);
if (dep[x]!=dep[y]){
int j=zjy[dep[x]];
while (j>=0){
if (dep[f[x][j]]>=dep[y]) x=f[x][j];
j--;
}
}
if (x==y) return x;
int j=zjy[dep[x]];
while (j>=0){
if (f[x][j]!=f[y][j]){
x=f[x][j];
y=f[y][j];
}
j--;
}
return f[x][0];
}
void travel(int x,int y){
a[++top]=x;
int t=h[x];
size[x]=1;
while (t){
if (go[t]!=y&&!bz[go[t]]){
travel(go[t],x);
size[x]+=size[go[t]];
}
t=next[t];
}
}
void dg(int x,int y,int z,int w){
belong[x][w]=z;
int t=h[x];
while (t){
if (go[t]!=y&&!bz[go[t]]){
d[go[t]][w]=d[x][w]+(ll)dis[t];
dg(go[t],x,z,w);
}
t=next[t];
}
}
int solve(int x,int y){
top=0;
travel(x,0);
int i,j=x,k=0,t;
while (1){
t=h[j];
while (t){
if (go[t]!=k&&!bz[go[t]]&&size[go[t]]>top/2){
k=j;
j=go[t];
break;
}
t=next[t];
}
if (!t) break;
}
if (!y) rot[0]=j;
t=h[j];
while (t){
if (!bz[go[t]]){
//change(root[j],1,n,go[t],go[t]);
d[go[t]][y]=dis[t];
dg(go[t],j,j,y);
}
t=next[t];
}
bz[j]=1;
belong[j][y]=j;
t=h[j];
while (t){
if (!bz[go[t]]){
son[j]++;
k=solve(go[t],y+1);
sx[k]=son[j];
fa[k]=j;
}
t=next[t];
}
return j;
}
void bfs(int x,int y){
int i,j,z=p[x],w=rot[y],u,v;
if (x>nn){
rot[x]=rot[y];
}
else{
tot++;
rot[x]=tot;
fo(i,0,20){
//root[tot]=root[w];
fo(j,1,3) tree[tot][j]=tree[w][j];
d1[tot]=d1[w]+d[z][i];
s1[tot]=s1[w]+1;
if (i){
d2[tot]=d2[w]+d[z][i-1];
s2[tot]=s2[w]+1;
}
if (belong[z][i]==z) break;
u=sx[belong[z][i+1]];
v=son[belong[z][i]];
//change(root[tot],1,v,u,tot+1);
tree[tot][u]=tot+1;
tot++;
//w=query(root[w],1,v,u);
w=tree[w][u];
}
}
int t=h[x];
while (t){
if (go[t]!=y) bfs(go[t],x);
t=next[t];
}
}
void calc(int x,int f){
if (!x) return;
int i,y=rot[x];
fo(i,0,20){
if (i){
ans-=f*d2[y];
ans-=(ll)f*s2[y]*d[k][i-1];
}
ans+=f*d1[y];
ans+=(ll)f*s1[y]*d[k][i];
if (belong[k][i]==k) break;
//y=query(root[y],1,son[belong[k][i]],sx[belong[k][i+1]]);
y=tree[y][sx[belong[k][i+1]]];
}
}
void write(ll x){
if (!x){
putchar('0');
putchar('\n');
return;
}
top=0;
while (x){
sta[++top]=x%10;
x/=10;
}
while (top) putchar(sta[top--]+'0');
putchar('\n');
}
int main(){
freopen("dis.in","r",stdin);freopen("dis.out","w",stdout);
czy=read();
n=read();m=read();
nn=n;
fo(i,1,n-1){
j=read();k=read();l=read();
add(j,k,l);add(k,j,l);
}
new_build(1,0);
fo(i,1,n) h[i]=h2[i];
fo(i,1,num){
go[i]=g2[i];
dis[i]=di2[i];
next[i]=n2[i];
}
dfs(1,0);
fo(i,1,n) zjy[i]=floor(log(i)/log(2));
fo(j,1,zjy[n])
fo(i,1,n)
f[i][j]=f[f[i][j-1]][j-1];
fo(i,1,nn) p[i]=read();
tot=top=cnt=0;
solve(1,0);
fo(i,1,n)
if (sx[i]) tree[fa[i]][sx[i]]=i;
tot=n;
fo(i,1,nn) zs[i]=i;
bfs(1,0);
while (m--){
l=read();r=read();k=read();
l^=(czy*ans);r^=(czy*ans);k^=(czy*ans);
ans=0;
calc(l,1);
calc(r,1);
j=zs[lca(l,r)];
calc(j,-1);
j=zs[f[j][0]];
calc(j,-1);
write(ans);
}
}