注:本系列只为整理、保存比赛模板用,并非代码均为自己所写。会给出原代码的链接。
题号:HDU6430
题意:一棵树上每个节点权值为v[i],每个节点的heard值是:以它为LCA的两个节点的GCD的最大值,要求输出每个节点的heard值。
代码来源(有改动):https://blog.youkuaiyun.com/a1325136367/article/details/82019663
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n;
int w[100010],siz[100010],son[100010]={0},cnt=0,ans[100010],vis[100010],edgcnt=1;
int id[100010],ls[100010],rs[100010],head[100010],num[100010]={0};
vector<int>fac[100010];
struct node{
int u,v,nxt;
}e[100010];
inline void addedg(int u,int v){e[edgcnt]={u,v,head[u]},head[u]=edgcnt++;}
int pre_dfs(int x,int fa){
siz[x]=1;
ls[x]=rs[x]=++cnt;
id[cnt]=x;
for(int i=head[x];i!=-1;i=e[i].nxt){
int v=e[i].v;
if(v==fa)continue;
rs[x]=max(pre_dfs(v,x),rs[x]);
if(siz[v]>siz[son[x]])son[x]=v;
}
siz[fa]+=siz[x];
return rs[x];
}
void update(int x,int c){
int len=fac[x].size();
for(int i=0;i<len;i++){
int t=fac[x][i];
num[t]+=c;
}
}
int query(int x){
int len=fac[x].size();
int ret=-1;
for(int i=0;i<len;i++){
int t=fac[x][i];
if(num[t])ret=max(ret,t);
}
return ret;
}
void dfs(int x,int fa,int b){
for(int i=head[x];i!=-1;i=e[i].nxt){
int v=e[i].v;
if(v==fa||v==son[x])continue;
dfs(v,x,0);
}
if(son[x])dfs(son[x],x,1);
for(int i=head[x];~i;i=e[i].nxt){
int v=e[i].v;
if(v==son[x])continue;
for(int j=ls[v];j<=rs[v];j++){
ans[x]=max(ans[x],query(w[id[j]]));
}
for(int j=ls[v];j<=rs[v];j++){
update(w[id[j]],1);
}
}
ans[x]=max(ans[x],query(w[x]));
update(w[x],1);
if(!b){
for(int i=ls[x];i<=rs[x];i++){
update(w[id[i]],-1);
}
}
}
int main(){
memset(head,-1,sizeof(head));
memset(ans,-1,sizeof(ans));
cin>>n;
siz[0]=-1;
fac[1].push_back(1);
for(int i=2;i<=100000;i++){
fac[i].push_back(1);
fac[i].push_back(i);
for(int j=i+i;j<=100000;j+=i){
fac[j].push_back(i);
}
}
for(int i=2;i<=n;i++){
int f;
scanf("%d",&f);
addedg(f,i);
}
for(int i=1;i<=n;++i){
scanf("%d",&w[i]);
}
pre_dfs(1,0);
dfs(1,0,0);
for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
}