题解:我们考虑维护每个点到根路径的异或和 这样的话两个数异或就等于这条路径的异或和 这样的话我们可以用莫队转移 然后用字典树贪心统计答案
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=5e4+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,m,q;
int a[MAXN],pos[21];ll ans2[MAXN];
void dfs(int x,int pre){
link(x){
if(j->t!=pre){a[j->t]=(a[x]^(j->v));dfs(j->t,x);}
}
}
int p[MAXN],sz,cnt,rt;
typedef struct node{
int ch[2],num;
}node;
node d[MAXN*21];
void newnode(int &x){
x=++cnt;d[x].ch[0]=d[x].ch[1]=d[x].num=0;
}
void insert(int x){
int temp=rt;
for(int i=20;i>=0;i--){
int t=((x>>i)&1);
if(!d[temp].ch[t])newnode(d[temp].ch[t]);
temp=d[temp].ch[t];
d[temp].num++;
}
}
void Delete(int x){
int temp=rt;
for(int i=20;i>=0;i--){
int t=((x>>i)&1);
temp=d[temp].ch[t];
d[temp].num--;
}
}
int Calc(int x){
int temp=rt;int ans=0;
for(int i=20;i>=0;i--){
int t=((x>>i)&1);
if(pos[i]){
if(t)temp=d[temp].ch[0];
else temp=d[temp].ch[1];
}
else{
if(t)ans+=d[d[temp].ch[0]].num,temp=d[temp].ch[1];
else ans+=d[d[temp].ch[1]].num,temp=d[temp].ch[0];
}
}
return ans;
}
typedef struct Q{
int l,r,id;
friend bool operator<(Q aa,Q bb){
if(p[aa.l]==p[bb.l])return aa.r<bb.r;
else return p[aa.l]<p[bb.l];
}
}Q;
Q que[MAXN];
int main(){
while(scanf("%d%d%d",&n,&m,&q)!=EOF){
memset(h,0,sizeof(h));memset(e,0,sizeof(e));o=e;
dec(i,20,0)pos[i]=((m>>i)&1);
cnt=0;newnode(rt);
sz=(int)sqrt(n);
inc(i,1,n)p[i]=(i-1)/sz+1;
int u,v,vul;
inc(i,1,n-1)u=read(),v=read(),vul=read(),add(u,v,vul),add(v,u,vul);
dfs(1,0);
inc(i,1,q)que[i].l=read(),que[i].r=read(),que[i].id=i;
sort(que+1,que+q+1);
int L=1;int R=0;ll ans1=0;
for(int i=1;i<=q;i++){
while(R>que[i].r){
ans1-=Calc(a[R]);Delete(a[R]);
R--;
}
while(R<que[i].r){
R++;
ans1+=Calc(a[R]);insert(a[R]);
}
while(L<que[i].l){
ans1-=Calc(a[L]);Delete(a[L]);
L++;
}
while(L>que[i].l){
L--;
ans1+=Calc(a[L]);insert(a[L]);
}
ans2[que[i].id]=ans1;
}
inc(i,1,q)printf("%lld\n",ans2[i]);
}
return 0;
}
Tree
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 511 Accepted Submission(s): 210
Problem Description
There is a tree, whose vertices are labeled by 1, 2, …, N. They are connected by N–1 edges. Each edge has a weight.For any two vertices u and v, f(u,v) is xor(exclusive-or) sum of weights of all edges on the path from u to v.There are Q queries,for each query,giving you a interval [l,r], you should calculate the number of pairs (u,v) such that f(u,v) > M (
l≤u<v≤r) 。
Input
There are multiple test cases.
For each case contains 3 integers N, M and Q on a line. (1≤N,M,Q≤50000)
Each of the next N - 1 lines contains three space separated integers a, b and c denoting an edge between a and b, whose weight is c.(1≤a,b≤N,0≤c≤50000)
Each of the next Q lines contains two integers l and r.(1≤l≤r≤N)
For each case contains 3 integers N, M and Q on a line. (1≤N,M,Q≤50000)
Each of the next N - 1 lines contains three space separated integers a, b and c denoting an edge between a and b, whose weight is c.(1≤a,b≤N,0≤c≤50000)
Each of the next Q lines contains two integers l and r.(1≤l≤r≤N)
Output
For each query,output the answer in a line.
Sample Input
5 10 3 1 2 13 2 3 15 2 4 17 2 5 8 1 5 2 4 3 3
Sample Output
6 3 0