zoukankan      html  css  js  c++  java
  • 【分块】计蒜客17120 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor

    题意:给一棵树,每个点有权值。q次询问a,b,k,问你从a点到b点,每次跳距离k,权值的异或和?

    预处理每个点往其根节点的路径上隔1~sqrt(n)的距离的异或和,然后把询问拆成a->lca(a,b),lca(a,b)->b,讨论一下即可,细节比较多。

    队友的代码:

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int q,a[50004],fa[50004][18],s[50004][230],nxt[100005],to[100005],head[100005],en,sq,n,vis[50004],deep[50004];
    void add(int u,int v)
    {
    	nxt[++en]=head[u];
    	head[u]=en;
    	to[en]=v;
    }
    int get(int now,int x)
    {
    	for(int i=17;i>=0;--i)
    	if(x>=(1<<i))
    	{
    		now=fa[now][i];
    		x-=(1<<i);
    	}
    	return now;
    }
    void dfs(int now)
    {
    	vis[now]=1;
    	for(int i=1;i<=17;++i)
    	{
    		fa[now][i]=fa[fa[now][i-1]][i-1];
    	}
    	for(int i=1;i<=sq;++i)
    	{
    		s[now][i]=s[get(now,i)][i]^a[now];
    	}
    	for(int i=head[now];i;i=nxt[i])
    	if(!vis[to[i]])
    	{
    		fa[to[i]][0]=now;
    		deep[to[i]]=deep[now]+1;
    		dfs(to[i]);
    	}
    }
    int lca(int u,int v)
    {
    	for(int i=17;i>=0;--i)
    	if(deep[fa[u][i]]>=deep[v])
    		u=fa[u][i];
    	for(int i=17;i>=0;--i)
    	if(deep[fa[v][i]]>=deep[u])
    		v=fa[v][i];
    	if(u==v)return u;
    	for(int i=17;i>=0;--i)
    	if(fa[u][i]!=fa[v][i])
    	{
    		u=fa[u][i];
    		v=fa[v][i];
    	}
    	return fa[u][0];
    }
    int main()
    {
    	while(scanf("%d%d",&n,&q)!=EOF)
    	{
    		int u,v,k;
    		for(int i=1;i<n;++i)
    		{
    			scanf("%d%d",&u,&v);
    			add(u,v);
    			add(v,u);
    		}
    		sq=sqrt(n);
    		for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    		deep[1]=1;
    		dfs(1);
    		for(int i=1;i<=q;++i)
    		{
    			scanf("%d%d%d",&u,&v,&k);
    			if(k<=sq)
    			{
    				int nowans=0;
    				int l=lca(u,v);
    				int l1=(deep[u]-deep[l])%k;
    				int ll=get(l,k-l1);
    				nowans^=s[u][k];
    				nowans^=s[ll][k];
    				int l2=(deep[v]-deep[l]);
    				if(l2>=k-l1&&v!=l)
    				{
    					l2-=(k-l1);
    					v=get(v,l2%k);
    					l1=(deep[v]-deep[l])%k;
    					if(l1==0) ll=l;
    					else ll=get(l,k-l1);
    					nowans^=s[v][k];
    					nowans^=s[ll][k];
    				}
    				printf("%d
    ",nowans);
    			}
    			else
    			{
    				
    				int nowans=0;
    				int l=lca(u,v);
    				int l1=(deep[u]-deep[l])%k;
    				int ll=get(l,k-l1);
    				int now=u;
    				while(deep[now]>=deep[l])
    				{
    					nowans^=a[now];
    					now=get(now,k);
    				}
    				int l2=(deep[v]-deep[l]);
    				if(l2>=k-l1&&v!=l)
    				{
    					l2-=(k-l1);
    					v=get(v,l2%k);
    					now=v;
    					while(deep[now]>deep[l])
    					{
    						nowans^=a[now];
    						now=get(now,k);
    					}
    				}
    				printf("%d
    ",nowans);
    			}
    		}
    		en=0;
    		for(int i=1;i<=n;++i)
    		{
    			head[i]=0;
    			for(int j=1;j<=sq;++j)
    				s[i][j]=0;
    			a[i]=0;
    			vis[i]=0;
    			deep[i]=0;
    			for(int j=0;j<=17;++j)
    			fa[i][j]=0;
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    实现将Web页面的内容,Export To Excel的功能
    设计模式点滴
    Vista上运行VisualStudio2005,调试asp.net程序的怪问题
    《天风文章》V1.0.0使用说明
    呵呵,cnblog排名进4000了,留念一下!
    一个程序只能启动一次实现
    VS中"生成注释WEB页"的问题
    用友Cell组件使用总结
    《天风文章》 V1.1.0设计文档
    SQL 数据库的自动备份(Procedures实现)
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7532506.html
Copyright © 2011-2022 走看看