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;
}

 

posted on 2015-11-28 22:39  ctlchild  阅读(137)  评论(0编辑  收藏  举报

导航