codeforces #425 D. Misha, Grisha and Underground (dfs+rmq在线求LCA,讨论了一年)

题目链接

题意:

给出一棵树,以及三个点(可能重合),问两两组成的3条路径中,哪2条路径重合部分最长。

思路:

LCA还是一下就能想到的,rmq+dfs在线求。

然后我开始分情况讨论,讨论了一年也没讨论完,哭哭

结论是:求出三个lca,并取深度最大的那个,就是我们要的三岔路口K,然后分别求出K到a,b,c三点的路径长度,取最大值+1就是答案。

所以我的问题在于,没有试图往一般性的方向考虑,以为讨论一下就可以了…

这大概就是所谓的猜结论?

感性的理解的话,LCA越深,意味着另一个点到LCA的距离越远,也就是相交的路径越长

但是我的话,估计还是很难在短短不到一个小时内得出这样一般性的结论orz…

这大概就是数学方面的天赋差距把…T T

  1/* ***********************************************
  2Author :111qqz
  3Created Time :2017年07月30日 星期日 15时12分34秒
  4File Name :D.cpp
  5 ************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <ctime>
 19#define fst first
 20#define sec second
 21#define lson l,m,rt<<1
 22#define rson m+1,r,rt<<1|1
 23#define ms(a,x) memset(a,x,sizeof(a))
 24typedef long long LL;
 25#define pi pair < int ,int >
 26#define MP make_pair
 27
 28using namespace std;
 29const double eps = 1E-8;
 30const int dx4[4]={1,0,0,-1};
 31const int dy4[4]={0,-1,1,0};
 32const int inf = 0x3f3f3f3f;
 33const int N=1E5+7;
 34int n,q;
 35vector < pi > edge[N];
 36int in[N];
 37int E[2*N],R[2*N],dis[N],depth[2*N];
 38int p;
 39int dp[2*N][20];
 40void dfs( int u,int dep,int d,int pre)
 41{
 42
 43    //  cout<<"u:"<<u<<" dep:"<<dep<<" d:"<<d<<endl;
 44    p++;
 45    E[p] = u;
 46    depth[p] = dep;
 47    R[u] = p ;
 48    dis[u] = d;
 49
 50
 51    int siz = edge[u].size();
 52    for ( int i = 0 ; i < siz ; i++)
 53    {
 54	int v = edge[u][i].fst;
 55	if (v==pre) continue;
 56	dfs(v,dep+1,d+edge[u][i].sec,u);
 57
 58	p++;
 59	E[p] = u;
 60	depth[p] = dep;
 61    }
 62}
 63
 64
 65
 66int _min( int l,int r)
 67{
 68    if (depth[l]<depth[r]) return l;
 69    return r;
 70}
 71void rmq_init()
 72{
 73    for ( int i = 1 ; i <= 2*n+2 ; i++) dp[i][0] = i;
 74
 75    for ( int j = 1 ; (1<<j) <= 2*n+2 ; j++)
 76	for ( int i = 1 ; i + (1<<j)-1 <= 2*n+2 ; i++)
 77	    dp[i][j] = _min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
 78}
 79
 80int rmq_min( int l,int r)
 81{
 82    if (l>r) swap(l,r);
 83    int k = 0 ;
 84    while (1<<(k+1)<=r-l+1) k++;
 85    return _min(dp[l][k],dp[r-(1<<k)+1][k]);
 86}
 87int D(int u,int v) //计算u,v点的距离
 88{
 89    int LCA = E[rmq_min(R[u],R[v])];
 90    int res = dis[u] + dis[v] - 2*dis[LCA];
 91    return res;
 92}
 93/*
 94int solve( int a,int b,int c) //a->c,b->c
 95{
 96    int LCA = E[rmq_min(R[a],R[b])];
 97    int res = inf; //check分支
 98    printf("[%d %d] %d\n",a,b,LCA);
 99    printf("dis[c]:%i dis[LCA]:%i\n",dis[c],dis[LCA]);
100    if (dis[LCA]>dis[c])
101    {
102	int LCA3 = E[rmq_min(R[c],R[LCA])];
103
104//	if (dis[c]+D(c,LCA)==dis[LCA])
105//	    res = dis[LCA]-dis[c]+1;
106//	else
107	    if (D(c,LCA3)+D(LCA3,LCA)==D(c,LCA))
108		res = D(c,LCA)+1;
109    }
110    if (dis[LCA]==dis[c])
111    {
112
113	if (LCA==c) res = 1;
114	else res = D(c,LCA) + 1; //直接错把LCA固定在根了。。
115    }
116    if (dis[LCA]<dis[c])
117    {
118	int LCA1 = E[rmq_min(R[b],R[c])];
119	int LCA2 = E[rmq_min(R[a],R[c])];
120	printf("LCA1:%d LCA2:%d\n",LCA1,LCA2);
121	if (D(b,c)==D(b,a)+D(a,c))
122	{
123	    res =D(a,c)+1;
124//	    cout<<"1"<<endl;
125	}
126	else 
127	if (D(a,c)==D(a,b)+D(b,c))
128	{
129	    res = D(b,c)+1; 
130	   // cout<<"2"<<endl;
131	}
132	else 
133	if (D(LCA,a)==D(LCA,c) + D(c,a)||D(LCA,b)==D(LCA,c)+D(c,b))
134	{
135	    res  = 1; //只在c点汇合
136	  //  cout<<"3:"<<endl;
137	}
138	else
139	if (D(c,LCA1)+D(LCA1,b)==D(c,b)&&D(c,LCA)+D(LCA,b)!=D(c,b)) //在靠近b的另外分支
140	{
141	    if (D(LCA,LCA1)==dis[c]-dis[LCA1])
142	    res = D(c,LCA1)+1;
143	    else res = D(c,LCA)+1;
144	    cout<<"4:"<<endl;
145	}
146	else
147	if (D(c,LCA2)+D(LCA2,a)==D(c,a)&&D(c,LCA)+D(LCA,a)!=D(c,a))
148	{
149	    if (D(LCA,LCA2)==dis[c]-dis[LCA])
150		res = D(c,LCA2) + 1;
151	    else res = D(c,LCA)+1;
152	    cout<<"5:"<<endl;
153	}
154    }
155    return res;
156}
157 */
158int max_dep3(int a,int b,int c)
159{
160    int ret = 0;
161    int mx = -1;
162    if (dis[a]>mx)
163    {
164	mx = dis[a];
165	ret = a;
166    }
167    if (dis[b]>mx)
168    {
169	mx = dis[b];
170	ret = b;
171    }
172    if (dis[c]>mx)
173    {
174	mx = dis[c];
175	ret = c;
176    }
177    return ret;
178}
179int max3( int a,int b, int c)
180{
181    int mx = -1;
182    mx = max(a,b);
183    mx = max(mx,c);
184    return mx;
185}
186
187int main()
188{
189#ifndef  ONLINE_JUDGE
190    freopen("./in.txt","r",stdin);
191#endif
192
193    ms(in,0);
194    scanf("%d %d",&n,&q);
195    for ( int i = 2 ; i <= n ; i++)
196    {
197	int x;
198	scanf("%d",&x);
199	edge[i].push_back(make_pair(x,1));
200	edge[x].push_back(make_pair(i,1));
201    }
202    p = 0 ;
203    dfs(1,0,0,-1);
204    rmq_init();
205
206    while (q--)
207    {
208	int a,b,c;
209	scanf("%d%d%d",&a,&b,&c);
210	vector<int>ret;
211	int LCA = max_dep3(E[rmq_min(R[a],R[b])],E[rmq_min(R[b],R[c])],E[rmq_min(R[a],R[c])]);
212	int ans = max3(D(LCA,a),D(LCA,b),D(LCA,c))+1;
213	printf("%d\n",ans);
214//	printf("%d\n",solve(a,b,c));
215    }
216#ifndef ONLINE_JUDGE
217    fclose(stdin);
218#endif
219    return 0;
220}