BC#64 4.Tree
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5589
对于u,v的xor和就是u到根的xor和 xor上 v到根的xor和。看到n<=5w,考虑莫队,因为要xor和>m,那么用二进制拆分的思想,建一棵字典树,维护字典树的子树大小。显然>m时,从大到小枚举二进制位,存在xor和的某个二进制位为1而m的为0。时间复杂度:q*n^1/2*log(c)
(比赛时没想到字典树,哭瞎。还是太弱了TAT
#include<cstring> #include<algorithm> #include<iostream> #include<cstdio> #include<queue> #include<set> #include<cmath> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define maxn 70050 #define inf int(1e9) #define mm 1000000007 #define esp 1e-6 using namespace std; #define ll long long struct edge{int obj,pre,c; }e[maxn*2]; struct data{int l,r,id,ans,b; }q[maxn]; int head[maxn],a[maxn],cnt[maxn*2]; int n,m,Q,tot,ans,l,r; int read(){ int 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; } void dfs(int u,int fa){ for (int j=head[u];j;j=e[j].pre){ int v=e[j].obj; if (v!=fa) { a[v]=a[u]^e[j].c; dfs(v,u); } } } void insert(int x,int y,int z){ e[++tot].obj=y; e[tot].pre=head[x]; head[x]=tot; e[tot].c=z; } void add(int x){ int u=a[x],now=1; down(i,15,0){ if (((m>>i)&1)==0) ans+=cnt[now<<1|((u>>i&1)^1)]; now=now<<1|((u^m)>>i&1); } now=1; down(i,15,0){ cnt[now<<1|(u>>i&1)]++; now=now<<1|(u>>i&1); } } void del(int x){ int u=a[x],now=1; down(i,15,0){ cnt[now<<1|(u>>i&1)]--; now=now<<1|(u>>i&1); } now=1; down(i,15,0){ if (((m>>i)&1)==0) ans-=cnt[now<<1|((u>>i&1)^1)]; now=now<<1|((u^m)>>i&1); } } bool cmp(data a,data b){ return (a.b==b.b&&a.r<b.r)||(a.b<b.b); } int main(){ while (~scanf("%d%d%d",&n,&m,&Q)){ tot=0; clr(head,0); clr(cnt,0); int x,y,z; rep(i,1,n-1){ x=read(); y=read(); z=read(); insert(x,y,z); insert(y,x,z); } dfs(1,0); int block=int(sqrt(n)); rep(i,1,Q){ q[i].l=read(); q[i].r=read(); q[i].id=i; q[i].b=q[i].l/block+1; } sort(q+1,q+1+Q,cmp); ans=0; l=1; r=0; rep(i,1,Q){ int now=q[i].id; while (r<q[i].r) add(++r); while (r>q[i].r) del(r--); while (l>q[i].l) add(--l); while (l<q[i].l) del(l++); q[now].ans=ans; } rep(i,1,Q) printf("%d\n",q[i].ans); } return 0; }