hdu5589Tree

题解:我们考虑维护每个点到根路径的异或和 这样的话两个数异或就等于这条路径的异或和 这样的话我们可以用莫队转移 然后用字典树贪心统计答案

#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 (lu<vr) 。
 

 

Input
There are multiple test cases.
For each case contains 3 integers N, M and Q on a line.(1N,M,Q50000)
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.(1a,bN,0c50000)
Each of the next Q lines contains two integers l and r.(1lrN)
 

 

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
 
posted @ 2018-11-12 20:35  wang9897  阅读(127)  评论(0编辑  收藏  举报