Problem E. TeaTree
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 647 Accepted Submission(s): 232
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.
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
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.
Sample Input
4
1 1 3
4 1 6 9
Sample Output
2
-1
3
-1
Source
2018 Multi-University Training Contest 10
Recommend
chendu | We have carefully selected several similar problems for you: 6437 6436 6435 6434 6433
题意:
给出一颗树,给出每个点的val,要求输出树上所有点的最大价值,最大价值定义为
ans[X]=max(gcd(val[i],vaj[j])) i,j 满足 lca(i,j) = X
题意:
比赛的时候就一直在讨论启发式合并该怎么写,但是怎么也没想到O(1)的答案更新方法,只会用set维护答案,感觉复杂度是O(n^(3/2)* (log n)^2) 的 怎么样都是不可做的样子。
比赛后听了大神的思路,感觉启发式合并贼tm正确。直接O(n^(1/2))暴力去更新删除就可以了 比赛时候怎么也没想到 ,真的是太2B了。 总复杂度O(n^(3/2)* (log n)) 给了4s 轻轻松松就能过了。
只跑了400ms 快的飞起。
PS: 标程跑了3800ms,结果就给了4s 时限,真的是恶趣味的出题人。 或许 这就是高中生大佬吧。
感觉这个代码改改以后就拿这个当模板了
#include
using namespace std;
const int MAX=3e5+10;
vector<int> V[MAX];
class Edge {
public:
int v,next;
long long w;
};
int n;
int tot;
int head[MAX];
Edge edge[MAX<<1];
long long values[MAX];
void init() {
memset(head,-1,sizeof head);
tot=0;
}
void add(int u,int v) {
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot;
tot++;
}
int sz[MAX],wson[MAX];
void dfs1(int u,int pre) {
sz[u]=1;
for(int i=head[u]; i!=-1; i=edge[i].next) {
int v = edge[i].v;
if(v==pre) continue;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>sz[wson[u]]) wson[u]=v;
}
}
int val[MAX];
int vis[MAX];
int num[MAX];
int divs[MAX];
int tmp ;
vector<int> temp;
void add_node(int u) {
num[val[u]]++;
int cnt;
if(num[val[u]]==1) {
for(int i=0; ivoid det_node(int u) {
num[val[u]]--;
int cnt;
if(num[val[u]]==0) {
for(int i=0; ivoid add_tree(int u,int pre) {
temp.push_back(u);
for(int i=head[u]; i!=-1; i=edge[i].next) {
int v = edge[i].v;
if(v==pre) {
continue;
}
add_tree(v,u);
}
}
void det_tree(int u,int pre) {
det_node(u);
for(int i=head[u]; i!=-1; i=edge[i].next) {
int v = edge[i].v;
if(v==pre) {
continue;
}
det_tree(v,u);
}
}
int ans[MAX];
void dfs2(int u,int pre) {
if(sz[u]==1) {
ans[u] = -1;
add_node(u);
return;
}
for(int i=head[u]; i!=-1; i=edge[i].next) {
int v = edge[i].v;
if(v==wson[u] || v==pre) continue;
dfs2(v,u);
det_tree(v,u);
}
dfs2(wson[u],u);
tmp=0;
int cnt;
for(int i=head[u]; i!=-1; i=edge[i].next) {
temp.clear();
int v = edge[i].v;
if(v==wson[u] || v==pre) continue;
add_tree(v,u);
for(int j=0; jfor(int i=0; i//divs[cnt]++;
if(divs[cnt]) {
tmp = max(tmp,cnt);
}
}
}
for(int j=0; jfor(int i=0; i//divs[cnt]++;
if(divs[cnt]) {
tmp = max(tmp,cnt);
}
}
num[val[u]]++;
if(num[val[u]]==1) {
for(int i=0; iint main() {
// freopen("5.in","r",stdin);
// freopen("5.out","w",stdout);
for(int i=1; i<100005; i++) {
for(int j=1; j*i<100005; j++) {
V[i*j].push_back(i);
}
}
init();
scanf("%d",&n);
for(int i=1; i<=n; i++) {
ans[i]=-1;
}
int u;
for(int i=2; i<=n; i++) {
scanf("%d",&u);
add(u,i);
//add(i,u);
}
for(int i=1; i<=n; i++) {
scanf("%d",&val[i]);
}
dfs1(1,-1);
dfs2(1,-1);
for(int i=1; i<=n; i++) {
printf("%d\n",ans[i]);
}
}