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<<"\n";
    }
    return 0;
}

 

posted on 2017-07-26 20:27  lazzzy  阅读(192)  评论(0编辑  收藏  举报

导航