zoukankan      html  css  js  c++  java
  • Codeforces Round #620 (Div. 2)E LCA

    题:https://codeforces.com/contest/1304/problem/E

    题意:给定一颗树,边权为1,m次询问,每次询问给定x,y,a,b,k,问能否在原树上添加x到y的边,a到b的路径长度等于k,注意这里的点和边都是可以重复走的;

    分析:注意到点边可以重复走,我们就可以推出一个条件就是a、b之间的长度len要满足>=k;

       其次当路长大于k时,我们就要判断len和k是否同奇偶,因为要到达长度len要被分为:len=k+2*i(i>=0),否则无法构造出这么一条路径

       然后添加x-y造成的路径选择,有分为最简单的3种

       1、直接走a,b;

       2、走a-x-y-b;

       3、走a-y-x-b;

       然后树上路径就用倍增lca模板即可求俩点间距离

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    #define pb push_back
    const int M=2e5+4;
    const int N=20;
    struct node{
        int v,w;
        node(int vv=0,int ww=0):v(vv),w(ww){}
    };
    vector<node>e[M];
    int s,grand[M][N],dis[M][N],deep[M],root,n;
    void dfs(int u){
        for(int i=1;i<=s;i++){
            grand[u][i]=grand[grand[u][i-1]][i-1];
            dis[u][i]=dis[u][i-1]+dis[grand[u][i-1]][i-1];
            if(!grand[u][i])
                break;
        }
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i].v;
            if(v!=grand[u][0]){
                grand[v][0]=u;
                deep[v]=deep[u]+1;
                dis[v][0]=e[u][i].w;
                dfs(v);
            }   // cout<<"!!"<<endl;
        }
    }
    void init(){
        s=floor(log(1.0*n)/log(2.0));
        deep[0]=-1;
        dfs(root);
    }
    int LCA(int a,int b){
        if(deep[a]>deep[b])
            swap(a,b);
        int ans=0;
        for(int i=s;i>=0;i--){
            if(deep[b]>deep[a]&&deep[a]<=deep[grand[b][i]])
                ans+=dis[b][i],b=grand[b][i];
        }
        for(int i=s;i>=0;i--)
            if(grand[a][i]!=grand[b][i])
                ans+=dis[a][i]+dis[b][i],b=grand[b][i],a=grand[a][i];
        if(a!=b)
            ans+=dis[a][0]+dis[b][0];
        return ans;
    }
    bool check(int a,int b){
        return b>=a&&(a%2)==(b%2); 
    }
    int main(){
    
        scanf("%d",&n);
        for(int v,u,i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            e[u].pb(node(v,1));
            e[v].pb(node(u,1));
        }
        root=1;
        init();
        int m;
        scanf("%d",&m);
        while(m--){
            int x,y,a,b,k;
            scanf("%d%d%d%d%d",&x,&y,&a,&b,&k);
        ///    cout<<LCA(a,b)<<endl;
            if(check(LCA(a,b),k)||check(LCA(a,x)+1+LCA(y,b),k)||check(LCA(a,y)+1+LCA(x,b),k))
                puts("YES");
            else
                puts("NO");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Allegro PCB Design GXL (legacy) 使用slide无法将走线推挤到焊盘的原因
    OrCAD Capture CIS 16.6 导出BOM
    Altium Designer (17.0) 打印输出指定的层
    Allegro PCB Design GXL (legacy) 将指定的层导出为DXF
    Allegro PCB Design GXL (legacy) 设置十字大光标
    Allegro PCB Design GXL (legacy) 手动更改元器件引脚的网络
    magento产品导入时需要注意的事项
    magento url rewrite
    验证台湾同胞身份证信息
    IE8对css文件的限制
  • 原文地址:https://www.cnblogs.com/starve/p/12331987.html
Copyright © 2011-2022 走看看