题意:在一棵树上每次在一个节点上增加两个子节点,问每次更新后树上的最长的一条链是多少。
设最长链的长度为len,链的两个端点为e1,e2,每次增加点的编号为a1,a2。
开始时,显然有len = 2,且可以有 e1 = 2,e2 = 3。
每次通过判断a1与e1,e2之间的较长的一段是否大于len,若不大于则无需更新。
若大于则更新相应节点,若较长一段为a1与e1,则令e2 = a1,否则 令 e1 = a1。
因为a1,a2的父节点相同,所以比较其中一个即可。
计算一条链的长度,设一条链的端点为 u , v ,则其长度必有 len = depth(u) + depth(v) - 2*depth(LCA(u,v));
#include <iostream> #include <algorithm> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <stack> #pragma comment(linker, "/STACK:1024000000"); #define LL long long int using namespace std; const int MAXN = 2000110; struct N { int v; N *next; }*head[MAXN]; N *creat() { N *p = (N *)malloc(sizeof(N)); p->next = NULL; return p; } void link(int u,int v) { N *p = creat(); p->v = v; p->next = head[u]->next; head[u]->next = p; } int point[2*MAXN],r[MAXN],depth[MAXN]; bool mark[MAXN]; int Max_Size; void dfs(int T,int h) { if(mark[T] == false) { mark[T] = true; r[T] = Max_Size; depth[T] = h; point[Max_Size++] = T; for(N *p = head[T]->next; p != NULL; p = p->next) { if(mark[p->v] == false) { dfs(p->v,h+1); point[Max_Size++] = T; } } } } struct ST { int h,v; }st[4*MAXN]; void Init_St(int site,int l,int r) { if(l == r) { st[site].v = point[l]; st[site].h = depth[point[l]]; return ; } int mid = (l+r)>>1; Init_St(site<<1,l,mid); Init_St(site<<1|1,mid+1,r); if(st[site<<1].h < st[site<<1|1].h) st[site] = st[site<<1]; else st[site] = st[site<<1|1]; } ST Query_Ancestor(int site,int L,int R,int l,int r) { if(L == l && R == r) { return st[site]; } int mid = (L+R)>>1; if(r <= mid) { return Query_Ancestor(site<<1,L,mid,l,r); } if(mid < l) { return Query_Ancestor(site<<1|1,mid+1,R,l,r); } ST a1,a2; a1 = Query_Ancestor(site<<1,L,mid,l,mid); a2 = Query_Ancestor(site<<1|1,mid+1,R,mid+1,r); if(a1.h < a2.h) return a1; return a2; } int main() { int i,n,u,m,top,q; ST anc; scanf("%d",&q); memset(mark,false,sizeof(bool)*(n+2)); n = q*2+10; for(i = 1; i <= n; ++i) { head[i] = creat(); } link(1,2); link(1,3); link(1,4); link(2,1); link(3,1); link(4,1); top = 5; for(i = 0; i < q; ++i) { scanf("%d",&u); link(u,top); link(top,u); top++; link(u,top); link(top,u); top++; } Max_Size = 1; dfs(1,1); Init_St(1,1,Max_Size-1); int e1 = 2,e2 = 3,Max_Diameter = 2,Temp_Diameter1,Temp_Diameter2; for(i = 1;i <= q; ++i) { u = i*2+4; if(r[u] < r[e1]) { anc = Query_Ancestor(1,1,Max_Size-1,r[u],r[e1]); } else { anc = Query_Ancestor(1,1,Max_Size-1,r[e1],r[u]); } Temp_Diameter1 = depth[u] + depth[e1] - anc.h*2; if(r[u] < r[e2]) { anc = Query_Ancestor(1,1,Max_Size-1,r[u],r[e2]); } else { anc = Query_Ancestor(1,1,Max_Size-1,r[e2],r[u]); } Temp_Diameter2 = depth[u] + depth[e2] - anc.h*2; if(Temp_Diameter1 >= Temp_Diameter2 && Temp_Diameter1 > Max_Diameter) { Max_Diameter = Temp_Diameter1; e2 = u; } else if(Temp_Diameter2 >= Temp_Diameter1 && Temp_Diameter2 > Max_Diameter) { Max_Diameter = Temp_Diameter2; e1 = u; } printf("%d\n",Max_Diameter); } return 0; }