Problem E. TeaTree
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1248 Accepted Submission(s): 478
Problem Description
Recently, TeaTree acquire new knoledge gcd (Greatest Common Divisor), now she want to test you.
As we know, TeaTree is a tree and her root is node 1, she have n nodes and n-1 edge, for each node i, it has it’s value v[i].
For every two nodes i and j (i is not equal to j), they will tell their Lowest Common Ancestors (LCA) a number : gcd(v[i],v[j]).
For each node, you have to calculate the max number that it heard. some definition:
In graph theory and computer science, the lowest common ancestor (LCA) of two nodes u and v in a tree is the lowest (deepest) node that has both u and v as descendants, where we define each node to be a descendant of itself.
As we know, TeaTree is a tree and her root is node 1, she have n nodes and n-1 edge, for each node i, it has it’s value v[i].
For every two nodes i and j (i is not equal to j), they will tell their Lowest Common Ancestors (LCA) a number : gcd(v[i],v[j]).
For each node, you have to calculate the max number that it heard. some definition:
In graph theory and computer science, the lowest common ancestor (LCA) of two nodes u and v in a tree is the lowest (deepest) node that has both u and v as descendants, where we define each node to be a descendant of itself.
Input
On the first line, there is a positive integer n, which describe the number of nodes.
Next line there are n-1 positive integers f[2] ,f[3], …, f[n], f[i] describe the father of node i on tree.
Next line there are n positive integers v[2] ,v[3], …, v[n], v[i] describe the value of node i.
n<=100000, f[i]<i, v[i]<=100000
Next line there are n-1 positive integers f[2] ,f[3], …, f[n], f[i] describe the father of node i on tree.
Next line there are n positive integers v[2] ,v[3], …, v[n], v[i] describe the value of node i.
n<=100000, f[i]<i, v[i]<=100000
Output
Your output should include n lines, for i-th line, output the max number that node i heard.
For the nodes who heard nothing, output -1.
For the nodes who heard nothing, output -1.
Sample Input
4
1 1 3
4 1 6 9
Sample Output
2
-1
3
-1
Source
思路:
对每个节点建一棵权值线段树,线段树上插入该点权值的所有的质因数。
更新答案时,我们从底层网上更新,每次将所有的质因数更新到其父节点,同时保留一个最大值。
总体大概就是这样,具体细节需要在敲的时候注意下。
代码如下:
#include <bits/stdc++.h> using namespace std; const int maxn=1e5+10; const int maxm=maxn*400; struct node {int u,v,next;}e[maxn]; int head[maxn],cnt=0; inline void add(int u,int v){e[cnt]=node{u,v,head[u]},head[u]=cnt++;} vector<int>vec[maxn]; inline void init(){ for (int i=1; i<maxn; i++) vec[i].push_back(1); for (int i=2; i<maxn; i++){ vec[i].push_back(i); for (int j=i+i; j<maxn; j+=i) vec[j].push_back(i); } } int root[maxn],tot,ls[maxm],rs[maxm],sum[maxm]; inline void pushUp(int rt){ if(ls[rt] && rs[rt]) sum[rt]=max(sum[ls[rt]],sum[rs[rt]]); else if(ls[rt]) sum[rt]=sum[ls[rt]]; else if(rs[rt]) sum[rt]=sum[rs[rt]]; } void build(int &rt,int l,int r,int pos){ if(!rt) rt=++tot; if(l==r){ sum[rt]=pos; return ; } int mid=l+r>>1; if(pos<=mid) build(ls[rt],l,mid,pos); if(pos>mid) build(rs[rt],mid+1,r,pos); pushUp(rt); } int merge(int rt,int prt,int &ans){ if(!rt||!prt) return rt^prt; if(sum[rt]==sum[prt]) ans=max(ans,sum[rt]); if(ls[rt] | ls[prt]) ls[rt]=merge(ls[rt],ls[prt],ans); if(rs[rt] | rs[prt]) rs[rt]=merge(rs[rt],rs[prt],ans); pushUp(rt); return rt; } int n,ans[maxn]; void dfs(int u){ ans[u]=-1; for (int i=head[u];~i;i=e[i].next){ dfs(e[i].v); root[u]=merge(root[u],root[e[i].v],ans[u]); } } int main(){ memset(head,-1,sizeof(head)); cnt=0,tot=0; init(); scanf("%d",&n); for (int fa,i=2; i<=n; i++){ scanf("%d",&fa); add(fa,i); } for (int x,i=1; i<=n; i++){ scanf("%d",&x); root[i]=0; for (int j=0; j<vec[x].size(); j++) build(root[i],1,maxn,vec[x][j]); } dfs(1); for (int i=1; i<=n; i++) printf("%d ",ans[i]); return 0; }