洛谷P3398 仓鼠找sugar

来源:互联网 发布:犀牛社淘宝论坛 编辑:程序博客网 时间:2024/06/11 15:45

裸的LCA。

对于每次询问,设a,b的LCA为A,c,d的LCA为B,分两种情况讨论:

1)A与B的深度相同,此时二人相遇的充要条件为A==B,即四个点的最近公共祖先相同。

2 ) A与B深度不同,设A的深度大于B的深度,若二人相遇,则c或d与A的LCA一定为A。

#include<cstdio>#include<vector>#define maxn 100005inline int fread(void){    char c;int num=0;    while((c=getchar())==' '||c=='\r'||c=='\n');    num+=c-'0';    while((c=getchar())>='0'&&c<='9')        num=num*10+c-'0';    return num;}inline void swap(int &a,int &b){    a^=b;b^=a;a^=b;    return;}int n,q,fa[maxn][20],deep[maxn];std::vector<int>sons[maxn];inline void dfs(int u,int f,int dep){    deep[u]=dep;fa[u][0]=f;    int v,mx=sons[u].size();    for(int i=0;i<mx;i++){        v=sons[u][i];        if(v!=f){            dfs(v,u,dep+1);        }    }    return;}inline int lca(int a,int b){    if(deep[a]<deep[b])swap(a,b);//make deep[a]>deep[b]    int i,j;    for(i=0;(1<<i)<=deep[a];++i);    --i;    for(j=i;j>=0;--j)        if(deep[a]-(1<<j)>=deep[b])            a=fa[a][j];    if(a==b)return a;    for(j=i;j>=0;--j)        if(fa[a][j]!=fa[b][j]&&fa[a][j]!=0)            a=fa[a][j],b=fa[b][j];    return fa[a][0];}int main(){//freopen("a.in","r",stdin);     int i,j,k,x,y,a,b,c,d;    n=fread();q=fread();    for(i=0;i<n-1;++i){        x=fread();y=fread();        sons[x].push_back(y);        sons[y].push_back(x);    }//Initialize    dfs(1,0,0);    for(j=1;(1<<j)<=n;++j)        for(int i=1;i<=n;++i)            if(fa[i][j-1]!=-1)                 fa[i][j]=fa[fa[i][j-1]][j-1];    //preprocess fathers    while(q){        a=fread();b=fread();        c=fread();d=fread();        int A=lca(a,b),B=lca(c,d);        if(deep[A]==deep[B]){            if(A==B)printf("Y\n");            else printf("N\n");            --q;continue;        }//case 1        if(deep[A]<deep[B]){            swap(A,B);swap(a,c);swap(b,d);        }//make deep[A]>deep[B]        if(lca(c,A)==A) printf("Y\n");        else if(lca(d,A)==A) printf("Y\n");        else printf("N\n");//case 2        --q;    }    return 0;}

0 0