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 (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