protagonist

小P的Civilization V

11070: 小P的Civilization V

时间限制: 1 Sec  内存限制: 128 MB
提交: 27  解决: 5
[提交] [状态] [讨论版] [命题人:admin]

题目描述

小P最近在玩Civilization V,游戏的地图是一棵树,树的每个节点都可以当作战场,刚开始每个节点的战斗加成为0

现在小P拥有两种人员:

一种是工人,每个工人会有一个起点u和终点v,工人可以使u−>v路径上每个节点的战斗加成+1

一种是骑兵,每个战士也有一个起点u和终点v,战士可以选择u−>v路径上任意节点战斗

现有m个工人和q个骑兵,问每个骑兵作战最多可以拥有多少战斗加成

 

输入

第一行三个整数n,m,q

接下来一行n−1个数,第i个数fi表示第i+1个节点的父亲

接下来m行,每行两个整数u,v,表示一个工人

接下来q行,每行两个整数u,v,表示一个骑兵

 

输出

q行,对于每个骑兵,输出他作战最多可以拥有多少战斗加成

 

样例输入

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

样例输出

3
5
3
5
5

 

提示

对于15%的数据,保证n,q≤1000
对于另外15%的数据,保证fi=i
对于另外10%的数据,保证所有u=v
对于另外10%的数据,保证工人的u=v
对于另外10%的数据,保证骑兵的u=v
对于100%的数据,保证n,q≤500,000且fi≤i

Solution:

树上差分,记得算一下平方的最大范围,否则会TLE,另外点权可以映射到边权上,注意小的细节就可以了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i <= (b); ++ i)
#define REP(j, a, b) for(int j = (a); j <= (b); ++ j)
#define PER(i, a, b) for(int i = (a); i >= (b); -- i)
using namespace std;
const int maxn=5e5+10;
template <class T>
inline void rd(T &ret){
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9'){
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}
int n,m,q,dh;
struct node{
    int v,w,nx;
}p[maxn*2];
int tot,head[maxn],tmp,depth[maxn],fa[maxn][25],cnt[maxn],val[maxn][20];
void addedge(int u,int v){p[++tot].v=v,p[tot].nx=head[u],head[u]=tot;}
void dfs(int x){
      REP(i,1,dh){
           fa[x][i]=fa[fa[x][i-1]][i-1];
      }
      for(int i=head[x];i;i=p[i].nx){
           int to=p[i].v;
           depth[to]=depth[x]+1;
           fa[to][0]=x;
           dfs(to);
      }
}
int lca(int x,int y){
     if(depth[x]<depth[y])swap(x,y);
     for(int i=dh;i>=0;i--){
         if(depth[x]>depth[y]&&depth[fa[x][i]]>=depth[y])x=fa[x][i];
     }
     PER(i,dh,0){
        if(fa[x][i]!=fa[y][i]){
            x=fa[x][i],y=fa[y][i];
        }
     }
     if(x!=y){
         return fa[x][0];
     }
     return x;
}
void gt(int cur){
    for(int i=head[cur];i;i=p[i].nx){
        int to=p[i].v;
        gt(to);
        cnt[cur]+=cnt[to];
    }
}
void dfs2(int x){
      REP(i,1,dh)val[x][i]=max(val[x][i-1],val[fa[x][i-1]][i-1]);
      for(int i=head[x];i;i=p[i].nx){
          int to=p[i].v;
          val[to][0]=cnt[to];
          dfs2(to);
      }
}
int lca2(int x,int y){
     if(depth[x]<depth[y])swap(x,y);
     int ans=0;
     for(int i=dh;i>=0;i--){
         if(depth[x]>depth[y]&&depth[fa[x][i]]>=depth[y])ans=max(ans,val[x][i]),x=fa[x][i];
     }
     PER(i,dh,0){
        if(fa[x][i]!=fa[y][i]){
            ans=max(ans,max(val[x][i],val[y][i]));
            x=fa[x][i],y=fa[y][i];
        }
     }
     if(x!=y){
         ans=max(ans,max(val[x][0],val[y][0]));
         ans=max(ans,cnt[fa[x][0]]);
         return ans;
     }
     ans=max(ans,cnt[x]);
     return ans;
}
int main(){
    rd(n),rd(m),rd(q);
    depth[1]=1;
    dh=floor(log(n+0.0)/log(2.0));
    REP(i,2,n){
        rd(tmp);
        addedge(tmp,i);
    }
    dfs(1);
    REP(i,1,m){
        int u,v;
        rd(u),rd(v);
        int LCA=lca(u,v);
        cnt[u]++,cnt[v]++,cnt[LCA]--,cnt[fa[LCA][0]]--;
    }
    gt(1);
    dfs2(1);
    REP(i,1,q){
         int u,v;
         rd(u),rd(v);
         printf("%d\n",lca2(u,v));
    }
    return 0;
}

 

posted @ 2019-02-18 21:39  czy-power  阅读(260)  评论(0编辑  收藏  举报