穿过繁花森林,小 T
来到一个瀑布前。小 T
像往常一样戏水,但今天小 T
在瀑布后发现了一个密室。小 T
小心翼翼地走了进去,看见一块灵石悬浮在空中,小 T
突然明白了为什么这座山上的花开得这么茂盛。小 T
正想上前查看,却被一股神秘的力量挡住,紧接着不知从何处传来了声音:“想要接近我,先回答一个问题……”
给你一棵 n n n 个结点的有根树,树的根为 1 1 1 。一共有 q q q 次操作,第 i i i 次操作选定 k i k_i ki 个点 p 1 , p 2 , … , p k i p_1, p_2,\dots, p_{k_i} p1,p2,…,pki ,对每个点 x x x 定义 f x , i = max j = 1 k i { d i s t ( x , p j ) } f_{x,i} = \max^{k_i}_{j=1} \{dist(x, p_j )\} fx,i=maxj=1ki{dist(x,pj)} ,其中 d i s t ( x , y ) dist(x, y) dist(x,y) 表示树上 x , y x, y x,y 两点间最短路经过的边数。再对每个点 x x x 定义 g x = min i = 1 q { f x , i } g_x = \min^q_{i=1} \{f_{x,i}\} gx=mini=1q{fx,i} ,对于每个点你需要求出 g x g_x gx 。
听完这个问题后,小 T
顿时就蒙圈了。但小 T
对灵石非常地好奇,你能帮帮小 T
解决这个问题吗?
输入共 ( q + 3 ) (q + 3) (q+3) 行。
第一行一个正整数 n n n ,表示树上的结点数。
第二行 ( n − 1 ) (n − 1) (n−1) 个正整数,第 i i i 个数表示 i + 1 i + 1 i+1 号结点的父亲 a i + 1 a_{i+1} ai+1。
第三行一个正整数 q q q ,表示操作次数。
接下来 q q q 行,每行最开始有一个正整数 k i k_i ki,接下来输入 k i k_i ki 个互不相同的正整数 p 1 , p 2 , … , p k i p_1, p_2,\dots, p_{k_i} p1,p2,…,pki ,其意义见【题目描述】。
输出 n n n 行,第 i i i 行输出一个整数 g i g_i gi ,其意义见【题目描述】。
样例输入
8
1 1 2 2 3 4 4
2
3 5 6 7
2 2 8
样例输出
3
2
4
1
3
5
2
2
样例解释
第一次操作的 f f f 值为 3 , 3 , 4 , 4 , 4 , 5 , 5 , 5 3, 3, 4, 4, 4, 5, 5, 5 3,3,4,4,4,5,5,5 ;第二次操作的 f f f 值为 3 , 2 , 4 , 1 , 3 , 5 , 2 , 2 3, 2, 4, 1, 3, 5, 2, 2 3,2,4,1,3,5,2,2。
对于所有测试点,满足 1 ≤ n , q ≤ 3 × 1 0 5 , ∑ i = 1 q k i ≤ 1 0 6 , 1 ≤ a i , p i , k i ≤ n 1 \leq n, q \leq 3 \times 10^5,\sum^q_{i=1} k_i \leq 10^6,1 \leq a_i, p_i, k_i \leq n 1≤n,q≤3×105,∑i=1qki≤106,1≤ai,pi,ki≤n 。
每个子任务的具体限制见下表:
子任务编号 | 分值 | n ≤ n\leq n≤ | ∑ i = 1 q k i ≤ \sum^q_{i=1}k_i \leq ∑i=1qki≤ | 特殊限制 |
---|---|---|---|---|
1 1 1 | 10 10 10 | 400 400 400 | 400 400 400 | 无 |
2 2 2 | 20 20 20 | 3000 3000 3000 | 3000 3000 3000 | 无 |
3 3 3 | 20 20 20 | 3 × 1 0 5 3 \times 10^5 3×105 | 1 0 6 10^6 106 | 树是一条链 |
4 4 4 | 20 20 20 | 1 0 5 10^5 105 | 1 0 5 10^5 105 | 无 |
8 8 8 | 30 30 30 | 3 × 1 0 5 3 \times 10^5 3×105 | 1 0 6 10^6 106 | 无 |
成都七中 noip2020模拟
首先,树上最远点必须想到直径,这时我们发现无论多少个点,只有直径端点有用,所以我们动态维护直径。
但这题卡常,所以我们用
S
T
ST
ST 表
O
(
1
)
O(1)
O(1) 查询
l
c
a
lca
lca。
#include<bits/stdc++.h>
#define N 300005
using namespace std;
inline char GET_CHAR ( void )
{
static char buf[1<<23],*p1=buf,*p2=buf;
return p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2) ? EOF : *p1++;
}
inline int read ( void )
{
int x=0;char ch;
while ( !isdigit(ch=GET_CHAR()) ) ;
for ( x=ch^48;isdigit(ch=GET_CHAR()); ) x=(x<<1)+(x<<3)+(ch^48);
return x;
}
vector<int> to[N];
int ans[N],dep[N],f[N<<1][20],T=19,qt,e[21],pos[N<<1],tt[N][20];
void dfs(int x,int las){
f[++qt][0]=x;
pos[x]=qt;
for(int i=0;i<(int)to[x].size();++i){
int y=to[x][i];
if(y==las)continue;
dep[y]=dep[x]+1;
tt[y][0]=x;
for(int j=1;j<=T;++j)tt[y][j]=tt[tt[y][j-1]][j-1];
dfs(y,x);
f[++qt][0]=x;
}
}
inline int get(int x,int y){
x=pos[x],y=pos[y];
if(x>y)swap(x,y);
int k=(int)(log((double)(y-x+1))/log(2.0));
return (dep[f[x][k]]<dep[f[y-e[k]+1][k]])?f[x][k]:f[y-e[k]+1][k];
}
inline int calc(int x,int y){
return dep[x]+dep[y]-2*dep[get(x,y)];
}
inline int tow(int x,int de){
for(int i=T;i+1;--i)if(dep[tt[x][i]]>=de)x=tt[x][i];
return x;
}
char ls[3005];
void ot(int x){
if(x==0) {putchar('0'),putchar('\n');return;}
if(x<0) putchar('-'),x=-x;
int temp=0;
while(x) ls[++temp]=x%10+'0',x/=10;
while(temp) putchar(ls[temp--]);
putchar('\n');
}
inline void dfs2(int x,int las){
for(int i=0;i<(int)to[x].size();++i){
int y=to[x][i];
if(y==las)continue;
dfs2(y,x);
ans[x]=min(ans[x],ans[y]+1);
}
}
inline void dfs3(int x,int las){
if(las)ans[x]=min(ans[x],ans[las]+1);
for(int i=0;i<to[x].size();++i){
int y=to[x][i];
if(y==las)continue;
dfs3(y,x);
}
}
int main(){
int n=read();
e[0]=1;
for(int i=1;i<=19;++i)e[i]=e[i-1]<<1;
for(int i=2;i<=n;++i){
int x=read();
to[x].push_back(i);to[i].push_back(x);
}
dep[1]=1;
dfs(1,0);
memset(ans,0x3f,sizeof(ans));
for(int i=1;i<=19;++i){
for(int j=1;j<=qt-e[i]+1;++j){
f[j][i]=(dep[f[j][i-1]]<dep[f[j+e[i-1]][i-1]])?f[j][i-1]:f[j+e[i-1]][i-1];
}
}
int q=read();
while(q--){
int k=read();
int u=0,v=0,len=0;
while(k--){
int x=read();
if(u==0||v==0){
if(u==0)u=x;
else v=x;
if(u&&v)len=calc(u,v);
continue;
}
int lenu=calc(u,x),lenv=calc(v,x);
if(lenu<lenv)swap(lenu,lenv),swap(u,v);
if(lenu>len)v=x,len=lenu;
}
if(dep[u]<dep[v])swap(u,v);
int z=tow(u,dep[u]-(len>>1));
ans[z]=min(ans[z],(len>>1)+(len&1));
if(len&1){
ans[tt[z][0]]=min(ans[tt[z][0]],(len>>1)+(len&1));
}
}
dfs2(1,0);
dfs3(1,0);
for(int i=1;i<=n;++i)ot(ans[i]);
return 0;
}