魔法树 解题报告

题目描述
看到“没有就加上,有了就减去”,就应该可以想到异或操作;查询树上一段路径,可以直接树上差分。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define add(u,v,w) adds(u,v,w),adds(v,u,w)
using namespace std;
typedef long long ll;
inline int read(){
  register int x=0;
  char c=getchar();
  while(c<'0' || '9'<c) c=getchar();
  while('0'<=c && c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();
  return x;
}
const int N=5e5+1000,M=(1<<20)+100,mod=1e8+7;
int n,q,m,c[N],cost[M],d[N],val;
struct Edge{int from,to,dis;}e[N<<1];
int num,h[N];
void adds(int f,int t,int d){e[++num].from=h[f],e[num].to=t,e[num].dis=d,h[f]=num;}
//int f[N][21];
void dfs(int u,int fa){
  //f[u][0]=fa;
  //for(int i=1;i<=19;i++) f[u][i]=f[f[u][i-1]][i-1];
  for(int i=h[u];i;i=e[i].from){
    int v=e[i].to;
    if(v==fa) continue;
    d[v]=(d[u]^(1<<e[i].dis));
    dfs(v,u);
  }
}
int main(){
  freopen("mahou.in","r",stdin);
  freopen("mahou.out","w",stdout);
  n=read(),q=read(),m=read();
  for(int i=1,u,v,w;i<n;i++) u=read(),v=read(),w=read(),add(u,v,w-1);
  for(int i=0;i<m;i++) c[i]=read();
  for(int i=0;i<(1<<m);i++){
    cost[i]=1;
    for(int j=0;j<m;j++)
      if(i&(1<<j))
        cost[i]=1ll*cost[i]*c[j]%mod;
  }
  dfs(1,0);
  for(int i=1,u,v;i<=q;i++){
    u=read(),v=read();
    val=(d[u]^d[v]);//lca以上的部分自己异或掉了,不需要单独处理
    printf("%d\n",cost[val]);
  }
  return 0;
}

posted @ 2025-07-07 16:35  XiaoZi_qwq  阅读(4)  评论(0)    收藏  举报