Codeforces Round #425 D
题意:给一颗树,每个点权值为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; }