• Codeforces Round #425 D


    Misha, Grisha and Underground

    题意:给一颗树,每个点权值为1,q个询问,每个询问给出a,b,c,3 个点,选择一个点为起点,一个点为终点,形成一条路径,第3个点做为第二条路径的起点,问2条路径上重复区间的点权和的最大值

    思路:树链剖分或者LCA,树链剖分映射到数状数组上,没有更新,求出ab ac bc之间的权值和,最长的路径和第二长的路径重复的部分就是答案

    AC代码:

    #include "iostream"
    #include "string.h"
    #include "stack"
    #include "queue"
    #include "string"
    #include "vector"
    #include "set"
    #include "map"
    #include "algorithm"
    #include "stdio.h"
    #include "math.h"
    #define ll long long
    #define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
    #define mem(a) memset(a,0,sizeof(a))
    #define mp(x,y) make_pair(x,y)
    #define pb(x) push_back(x)
    #define lrt (root*2)
    #define rrt (root*2+1)
    #define len (r-l+1)
    #pragma comment(linker, "/STACK:102400000,102400000")
    using namespace std;
    const long long INF = 1e18+1LL;
    const int inf = 1e9+1e8;
    const int N=1e5+100;
    const ll mod=1e9+7;
    
    struct Edge{
        int next,to;
    };
    Edge e[N<<1];
    int n,q;
    int siz[N],son[N],tip[N],fa[N],dep[N],ran[N],top[N],cnt;
    int head[N],tot;
    int C[N];
    void add(int u, int v){
        e[tot].to=v;
        e[tot].next=head[u];
        head[u]=tot++;
    }
    void dfs1(int u, int f){
        siz[u]=1;
        fa[u]=f;
        dep[u]=dep[f]+1;
        for(int i=head[u]; i!=-1; i=e[i].next){
            int v=e[i].to;
            if(v==f) continue;
            dfs1(v,u);
            siz[u]+=siz[v];
            if(siz[v]>siz[son[u]]) son[u]=v;
        }
    }
    void dfs2(int u, int tp){
        tip[u]=++cnt;
        top[u]=tp;
        if(son[u]) dfs2(son[u], tp);
        for(int i=head[u]; i!=-1; i=e[i].next){
            int v=e[i].to;
            if(v!=son[u] && v!=fa[u]) dfs2(v,v);
        }
    }
    int lowbit(int x){
        return (-x)&x;
    }
    void add(int x){
        while(x<=n){
            C[x]+=1;
            x+=lowbit(x);
        }
    }
    int sum(int l, int r){
        int ret=0;
        l--;
        while(r>0){
            ret+=C[r];
            r-=lowbit(r);
        }
        while(l>0){
            ret-=C[l];
            l-=lowbit(l);
        }
        return ret;
    }
    int query(int u, int v){
        int ans=0;
        while(top[u]!=top[v]){
            if(dep[top[u]] < dep[top[v]]) swap(u,v);
            ans+=sum(tip[top[u]], tip[u]);
            u=fa[top[u]];
        }
        if(dep[u] > dep[v]) swap(u,v);
        ans+=sum(tip[u], tip[v]);
        return ans;
    }
    int main(){
        ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
        cin>>n>>q;
        memset(head,-1,sizeof(head));
        int to;
        for(int i=2; i<=n; ++i){
            cin>>to;
            add(i,to);
            add(to,i);
        }
        for(int i=1; i<=n; ++i){
            add(i);
        }
        dfs1(1,1);
        dfs2(1,1);
        int a,b,c,ans[5],anss;
        while(q--){
            cin>>a>>b>>c;
            ans[0]=query(a,b);
            ans[1]=query(a,c);
            ans[2]=query(b,c);
            sort(ans,ans+3);
            anss=ans[1]+ans[2]+1-ans[0]>>1;
            cout<<anss<<"
    ";
        }
        return 0;
    }
  • 相关阅读:
    待整理[图片验证码的破解]
    关于反爬的思索[集合]
    关于showdoc的服务器部署[转]
    jQuery插件实现多图片和单图片上传
    FTP 图片上传
    多线程(临界点处理)
    Python可迭代对象、迭代器和生成器
    一文搞懂Python函数(匿名函数、嵌套函数、闭包、装饰器)!
    Python比较操作符、变量赋值、对象拷贝
    Python并发编程——多线程与协程
  • 原文地址:https://www.cnblogs.com/max88888888/p/7241773.html
Copyright © 2020-2023  润新知