Tree
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 28 Accepted Submission(s): 7
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
求树上(i,j)边权异或和可以转换成i到根的异或和与j到根的异或和的异或和,那么如何求一个数和一些数的异或和大于M的个数呢?我们动态维护一颗字典树,支持插入和删除数字,同时支持查询,利用贪心思想很容易得到个数。如何动态维护当前询问字典树呢?当然考虑莫队了!
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#define Maxn 50010
#define ll long long
using namespace std;
struct edge{
int to,next,w;
}p[Maxn<<1];
int tot;
int head[Maxn];
int x[Maxn];
void addedge(int u,int v,int w){
p[tot].to=v;
p[tot].next=head[u];
p[tot].w=w;
head[u]=tot++;
}
void dfs(int u,int fa){
for(int i=head[u];i!=-1;i=p[i].next){
int v=p[i].to;
if(v==fa) continue;
x[v]=p[i].w^x[u];
dfs(v,u);
}
}
int pos[Maxn];
struct query{
int l,r,id;
bool operator<(const query &a)const{
return pos[l]<pos[a.l]||pos[l]==pos[a.l]&&r<a.r;
}
}q[Maxn];
int sz;
void init(int n,int t){
sz=(int)sqrt(n);
for(int i=0;i<n;i++) pos[i]=i/sz;
sort(q,q+t);
}
int M;
struct trie{
int ch[Maxn*30][2];
int val[Maxn*30];
int sz;
void init(){
sz=val[0]=0;
memset(ch[0],0,sizeof ch[0]);
}
void insert(int x){
int u=0;
for(int i=17;i>=0;i--){
int c=x>>i&1;
if(!ch[u][c]){
ch[u][c]=++sz;
val[sz]=0;
memset(ch[sz],0,sizeof ch[sz]);
}
u=ch[u][c];
val[u]++;
}
}
void del(int x){
int u=0;
for(int i=17;i>=0;i--){
int c=x>>i&1;
u=ch[u][c];
val[u]--;
}
}
ll query(int y){
int u=0;
ll ans=0;
for(int i=17;i>=0;i--){
int c=M>>i&1,d=y>>i&1;
if(c==1) u=ch[u][d^1];
else{
ans+=val[ch[u][d^1]];
u=ch[u][d];
}
if(!u) return ans;
}
return ans;
}
}tr;
ll res[Maxn];
void solve(int t){
tr.init();
ll ans=0;
int l=0,r=-1;
for(int i=0;i<t;i++){
while(r<q[i].r) ++r,ans+=tr.query(x[r]),tr.insert(x[r]);
while(q[i].l<l) --l,ans+=tr.query(x[l]),tr.insert(x[l]);
while(r>q[i].r) tr.del(x[r]),ans-=tr.query(x[r]),r--;
while(q[i].l>l) tr.del(x[l]),ans-=tr.query(x[l]),l++;
res[q[i].id]=ans;
}
}
int main()
{
int n,t,u,v,w;
while(~scanf("%d%d%d",&n,&M,&t)){
memset(head,-1,sizeof head);
tot=0;
for(int i=1;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
u--,v--;
addedge(u,v,w);
addedge(v,u,w);
}
x[0]=0;
dfs(0,-1);
for(int i=0;i<t;i++){
scanf("%d%d",&q[i].l,&q[i].r);
q[i].l--,q[i].r--,q[i].id=i;
}
init(n,t);
solve(t);
for(int i=0;i<t;i++)
printf("%I64d\n",res[i]);
}
return 0;
}