1. 程式人生 > >九校聯考DAY1T2(dp,換根與二次掃描法)

九校聯考DAY1T2(dp,換根與二次掃描法)

題目描述

銀企鵝非常擅長化學。有一天他在試圖命名一個巨大的單烯烴分子的時候,想到了一個問題。

給你一棵樹,一些邊有標記,對於每條有標記的邊,在樹中找到包含這條邊的一條最長鏈,並輸出長度。

輸入格式

第一行一個整數 id 表示測試點的編號。

多組資料,第二行一個整數 T 表示資料組數。

對於每組資料,第一行兩個整數 n, m 表示節點的個數,和被標記的邊的個數。

我們規定 1 是根,第二行 n-1 個整數給出 2到n 父親的編號,保證fai < i。

第三行 m 個整數範圍在 [2, n] 表示哪個點的父邊被標記過。

輸出格式

對於每組資料輸出一行 m 個整數,必須與輸入的邊順序一致,給出的是在這條邊必選的情況下樹中最長鏈的長度。

樣例資料

input

0
1
10 3
1 2 3 1 4 6 7 3 8
10 7 9

output

8 8 6

資料規模與約定

時間限制:3s

空間限制:512MB

(懶得分割了就這樣吧
因為要過給定邊
肯定是兩個點的兩邊各找一條最長鏈
比如求過邊(x,y)的最長鏈
fa[x]=y
x的一端很好處理
y的一端還需要往上處理一條最長
用往下的值再dfs一遍更新答案即可。

#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#define rep(i,j,k) for(int i = j;i <= k;++i) #define repp(i,j,k) for(int i = j;i >= k;--i) #define rept(i,x) for(int i = linkk[x];i;i = e[i].n) #define P pair<int,int> #define Pil pair<int,ll> #define Pli pair<ll,int> #define Pll pair<ll,ll> #define pb push_back #define pc putchar
#define mp make_pai #define file(k) memset(k,0,sizeof(k)) #define ll long long namespace fastIO{ #define BUF_SIZE 100000 #define OUT_SIZE 100000 bool IOerror = 0; inline char nc(){ static char buf[BUF_SIZE],*p1 = buf+BUF_SIZE, *pend = buf+BUF_SIZE; if(p1 == pend){ p1 = buf; pend = buf+fread(buf, 1, BUF_SIZE, stdin); if(pend == p1){ IOerror = 1; return -1;} } return *p1++; } inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} inline void read(int &x){ bool sign = 0; char ch = nc(); x = 0; for(; blank(ch); ch = nc()); if(IOerror)return; if(ch == '-') sign = 1, ch = nc(); for(; ch >= '0' && ch <= '9'; ch = nc()) x = x*10+ch-'0'; if(sign) x = -x; } inline void read(ll &x){ bool sign = 0; char ch = nc(); x = 0; for(; blank(ch); ch = nc()); if(IOerror) return; if(ch == '-') sign = 1, ch = nc(); for(; ch >= '0' && ch <= '9'; ch = nc()) x = x*10+ch-'0'; if(sign) x = -x; } #undef OUT_SIZE #undef BUF_SIZE }; using namespace fastIO; int n , m; int u , v; int fa[101000],dep[101000]; bool spe[101000]; int mx[101000] , nx[101000] , fmx[101000]; int id_m[101000] , id_n[101000]; int linkk[101000] , t; struct node{ int n , y; }e[201000]; queue<int>q; bool inq[101000]; int bfs(int S) { memset(inq,0,sizeof(inq)); inq[S] = true;q.push(S); int id; while(!q.empty()) { int x = q.front();q.pop(); id = x; rept(i,x) if(!inq[e[i].y]) inq[e[i].y] = true, q.push(e[i].y); } return id; } void dfss(int x) { dep[x] = dep[fa[x]] + 1; mx[x] = nx[x] = id_n[x] = id_m[x] = 0; int k = linkk[x]; if(x != 1 && e[k].n == 0) { id_m[x] = x; return; } rept(i,x) if(e[i].y != fa[x]) { dfss(e[i].y); if(mx[e[i].y]+1 > mx[x]) { nx[x] = mx[x] , id_n[x] = id_m[x]; mx[x] = mx[e[i].y] + 1,id_m[x] = id_m[e[i].y]; } else if(mx[e[i].y]+1 > nx[x]) nx[x] = mx[e[i].y] + 1,id_n[x] = id_m[e[i].y]; } } void dfs1(int x,int Max) { // if(x % 1000 == 0)printf("#%d %d\n",x,Max); if(x != 1) fmx[x] = Max; rept(i,x) { int y = e[i].y; if(y == fa[x]) continue; bool flag;int det; if(id_m[y] == id_m[x]) flag = false; else flag = true; if(Max != 0) Max > (flag?mx[x]:nx[x]) ? dfs1(y,Max+1) : dfs1(y,flag?mx[x]+1:nx[x]+1); else dfs1(y,flag?mx[x]+1:nx[x]+1); } } void insert(int x,int y) { e[++t].y = y;e[t].n = linkk[x];linkk[x] = t; e[++t].y = x;e[t].n = linkk[y];linkk[y] = t; } void init() { read(n);read(m);t = 0; rep(i,2,n) { read(fa[i]); insert(i,fa[i]); } dfss(1); dfs1(1,0); rep(i,1,m) { int x;read(x); int tmp = 0,Max = 0,y = fa[x]; if(id_m[y] != id_m[x]) Max = mx[y]; else Max = nx[y]; tmp = fmx[y]; Max = max(Max,tmp); printf("%d ",Max+1+mx[x],i); } printf("\n"); rep(i,1,n) linkk[i] = 0; } int main() { freopen("olefin.in","r",stdin); freopen("olefin.out","w",stdout); int T;read(T);read(T); while(T--)init(); return 0; }