5589

来源:互联网 发布:小白软件库 编辑:程序博客网 时间:2024/06/05 10:49
给定一棵树,每条边有一个权值,定义f(u,v)为树链(u,v)的异或和。Q次询问[l,r]中f(u,v)>M的个数。
对于一棵树,有f(u,v)=f(1,u)^f(1,v),然后就转化为一个序列上的问题。
答案用字典树维护。将每个数按数位从高到低插入字典树中(含前缀0)。对于询问就从字典树上往下走,(设这个数为x)每次走x当前位跟m当前位的异或值,如果m的当前位为0,就加上另一个节点的size。
不知道错哪了。欢迎来指正。
#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<map>#include<vector>#include<algorithm>using namespace std;#define rep(i,j,k) for(i=j;i<=k;++i)#define per(i,j,k) for(i=j;i>=k;--i)#define sqr(x) ((x)*(x))#define G getchar()#define LL long long#define pll pair<LL,LL>#define mkp make_pair#define X first#define Y second#define N 100005#define NN 1600005struct QUERY{int L,R,wz;}qu[N];int n,m,Q,numm[20];int tot,he[N],ne[N<<1],to[N<<1],W[N<<1];int a[N],mo[N],s,t;LL now,ans[N];int c[2][NN],stk[NN],Tp,mTp;LL cnt[NN];int read(){int x=0;char ch=G;for(;ch<48||ch>57;ch=G);for(;ch>47&&ch<58;ch=G)x=x*10+ch-48;return x;}void add(int x,int y,int z){to[++tot]=y;ne[tot]=he[x];W[tot]=z;he[x]=tot;}void DFS(int x,int e){int i,y;for(i=he[x];i;i=ne[i])if(i!=e){a[y=to[i]]=a[x]^W[i];DFS(y,i^1);}}bool cmp(QUERY x,QUERY y){return mo[x.L]==mo[y.L]?x.R<y.R:mo[x.L]<mo[y.L];}int get(){int rtn=stk[Tp++];mTp=max(mTp,Tp);c[0][rtn]=c[1][rtn]=cnt[rtn]=0;return rtn;}void ins(int x){int i,num[20];rep(i,0,19){num[i]=x&1;x>>=1;}x=1;per(i,19,0){int &y=c[num[i]][x];if(!y){y=get();c[0][y]=c[1][y]=0;}++cnt[x=y];}}void del(int x){int i,num[20],y;rep(i,0,19){num[i]=x&1;x>>=1;}x=1;per(i,19,0){int &y=c[num[i]][x];x=y;if(--cnt[y]==0){stk[--Tp]=y;y=0;}}}int cal(int x){int i,num[20],rtn=0;rep(i,0,19){num[i]=x&1;x>>=1;}x=1;per(i,19,0){if(!x)break;if(numm[i])x=c[!num[i]][x];else{rtn+=cnt[c[!num[i]][x]];x=c[num[i]][x];}}return rtn;}int main(){freopen("r.in","r",stdin);freopen("w.out","w",stdout);int i,x,y,z,l,r;per(i,NN-1,0)stk[i]=i;while(~scanf("%d%d%d",&n,&m,&Q)){s=ceil(sqrt(n));rep(i,1,n)he[i]=0,mo[i]=t+=i%s==1;tot=1;rep(i,2,n){x=read();y=read();z=read();add(x,y,z);add(y,x,z);}DFS(1,0);rep(i,1,Q){x=read();y=read();qu[i]=(QUERY){x,y,i};}sort(qu+1,qu+Q+1,cmp);per(i,mTp-1,2)stk[i]=i;mTp=Tp=2;c[0][1]=c[1][1]=0;ins(a[l=r=qu[1].L]);now=0;rep(i,0,19){numm[i]=m&1;m>>=1;}rep(i,1,n){while(r<qu[i].R){ins(a[++r]);now+=cal(a[r]);}while(r>qu[i].R){now-=cal(a[r]);del(a[r--]);}while(l>qu[i].L){ins(a[--l]);now+=cal(a[l]);}while(l<qu[i].L){now-=cal(a[l]);del(a[l++]);}ans[qu[i].wz]=now;}rep(i,1,Q)printf("%lld\n",ans[i]);}return 0;}

原创粉丝点击