zoukankan      html  css  js  c++  java
  • bzoj1787 [Ahoi2008]Meet 紧急集合

    Description

    Input

    Output

    Sample Input

    6 4
    1 2
    2 3
    2 4
    4 5
    5 6
    4 5 6
    6 3 1
    2 4 4
    6 6 6

    Sample Output


    5 2
    2 5
    4 1
    6 0

    HINT

    社会实践完滚回来想刷水结果被水题虐了

    先算出两两的lca,一定有两个lca是一样的

    假设对于询问(x,y,z),xy的lca是a,xz的lca是b,yz的lca是c,不妨设xyz不在链上,并且长成这样:

     

    那么一定有lca(a,z)=c,即lca(x,z)=c且lca(y,z)=c

    在同一链上更简单了

    然后只要把剩下的那个不同的lca当做集合的地点就好了,这个也很容易理解,自己画画图就好了

    QAQ因为数组开小而连跪3次……不要学我啊

    #include<cstdio>
    #include<iostream>
    using namespace std;
    #define LL long long
    #define N 1000010
    inline LL read()
    {
        LL x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    struct edge{
    	int to,next;
    }e[2*N];
    int head[N];
    int depth[N];
    int go[N][25];
    bool mrk[N];
    int n,m,cnt,x,y,z,xy,xz,yz,sum;
    inline int abs(int a)
    {return a<0?-a:a;}
    inline void ins(int u,int v)
    {
    	e[++cnt].to=v;
    	e[cnt].next=head[u];
    	head[u]=cnt;
    }
    inline void insert(int u,int v)
    {
    	ins(u,v);
    	ins(v,u);
    }
    inline void dfs(int x,int dep)
    {
    	if (mrk[x])return;
    	mrk[x]=1;depth[x]=dep;
    	for (int i=1;i<=20;i++) go[x][i]=go[go[x][i-1]][i-1];
    	for (int i=head[x];i;i=e[i].next)
    	  if (!mrk[e[i].to])
    	  {
    	  	go[e[i].to][0]=x;
    	  	dfs(e[i].to,dep+1);
    	  }
    } 
    inline int lca(int x,int y)
    {
    	if (depth[x]<depth[y])swap(x,y);
    	int res=depth[x]-depth[y];
    	for(int i=0;i<=19;i++)
    	  if (res & (1<<i)) x=go[x][i];
    	for (int i=19;i>=0;i--)
    	  if (go[x][i]!=go[y][i])
    	  {
    	  	x=go[x][i];
    	  	y=go[y][i];
    	  }
    	if (x==y)return x;
    	return go[x][0];
    }
    inline int dis(int a,int b)
    {
    	int t=lca(a,b);
    	return depth[a]+depth[b]-2*depth[t];
    }
    inline int calc()
    {
    	xy=lca(x,y); xz=lca(x,z); yz=lca(y,z);
    	int t;
    	if (xy==xz)t=yz;
    	if (xy==yz)t=xz;
    	if (xz==yz)t=xy;
    	int ans=dis(x,t)+dis(y,t)+dis(z,t);
    	printf("%d %d
    ",t,ans);
    }
    int main()
    {
    	n=read();m=read();
    	for (int i=1;i<n;i++)
    	{
    		int s=read(),t=read();
    		insert(s,t);
    	}
    	for(int i=0;i<20;i++)go[n/2][i]=n/2;
    	dfs(n/2,1);
    	for(int i=1;i<=m;i++)
    	{
    		x=read();
    		y=read();
    		z=read();
    		calc();
    	}
    }
    
    ——by zhber,转载请注明来源
  • 相关阅读:
    10 个深恶痛绝的 Java 异常。。
    为什么公司宁愿 25K 重新招人,也不给你加到 20K?原因太现实……
    推荐一款代码神器,代码量至少省一半!
    Spring Cloud Greenwich 正式发布,Hystrix 即将寿终正寝。。
    hdu 3853 LOOPS(概率 dp 期望)
    hdu 5245 Joyful(期望的计算,好题)
    hdu 4336 Card Collector(期望 dp 状态压缩)
    hdu 4405 Aeroplane chess(概率+dp)
    hdu 5036 Explosion(概率期望+bitset)
    hdu 5033 Building (单调栈 或 暴力枚举 )
  • 原文地址:https://www.cnblogs.com/zhber/p/4116388.html
Copyright © 2011-2022 走看看