HDU 6430 Problem E. TeaTree(虚树)
Problem E. TeaTree
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.
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6430
题意:
一棵树上每个节点权值为v[i],每个节点的heard值是:以它为LCA的两个节点的GCD的最大值,要求输出每个节点的heard值。
树节点个数1e5,权值为最大1e5。
思路:由于权值最大才1e5,开一个1e5的vector,考虑将树节点存入它权值因子的vector(比如权值为9的结点,将他存入v[1],v[3],v[9]里),然后按照每一个vector建立一棵虚树。将这颗虚树上除了叶子的点的答案都更新。但是由于只要更新非叶子节点的值,我就直接在建立虚树边的时候更新了,省去建边和搜索的过程。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #include<cmath> 6 using namespace std; 7 const int maxn = 100500; 8 9 struct Edge ///存原树 10 { 11 int to,next; 12 } E[maxn << 1]; 13 int frist[maxn], sign = 1; 14 inline void AddEdge(int u, int v) 15 { 16 E[sign].to = v; 17 E[sign].next = frist[u]; 18 frist[u] = sign++; 19 } 20 21 /* 22 struct void_tree ///存虚树 23 { 24 int to,next; 25 }vtree[maxn]; 26 int sign2=0,first2[maxn]; 27 inline void add_edge(int u, int v) 28 { 29 vtree[sign2].to = v; 30 vtree[sign2].next = first2[u]; 31 first2[u] = sign2++; 32 } 33 */ 34 int dfn[maxn]; ///dfs序 35 int deep[maxn]; ///节点深度 36 int s[maxn]; ///栈 37 int a[maxn]; ///存需要建立虚树的点 38 int index=0; 39 int top; ///栈顶 40 41 int fa[18][maxn]; 42 43 void dfs(int u) ///预处理dep和fa[0][j] 44 { 45 dfn[u] = ++index; 46 for(int i=frist[u];i;i=E[i].next) 47 { 48 if(E[i].to!=fa[0][u]) 49 { 50 deep[E[i].to]=deep[u]+1; 51 fa[0][E[i].to]=u; 52 dfs(E[i].to); 53 } 54 } 55 } 56 inline int LCA(int u,int v) ///求LCA 57 { 58 if(deep[u]>deep[v])swap(u,v); 59 for(int i=16;~i;i--) 60 if(deep[fa[i][v]]>=deep[u]) 61 v=fa[i][v]; 62 if(u==v)return u; 63 for(int i=16;~i;i--) 64 if(fa[i][u]!=fa[i][v]) 65 { 66 u=fa[i][u]; 67 v=fa[i][v]; 68 } 69 return fa[0][u]; 70 } 71 int answer[maxn]; 72 73 inline void insert_point(int x,int num) ///建立虚树 74 { 75 if(top == 0) 76 { 77 s[++top] = x; 78 return ; 79 } 80 int lca = LCA(x, s[top]); 81 if(lca == s[top]) 82 { 83 s[++top]=x; 84 return ; 85 } 86 while(top >= 1 && dfn[s[top - 1]] >= dfn[lca]) 87 { 88 answer[s[top - 1]]=num; ///不建边了,直接更新答案 89 //add_edge(s[top - 1], s[top]); 90 top--; 91 } 92 if(lca != s[top]) 93 { 94 answer[lca]=num; 95 //add_edge(lca, s[top]); 96 s[top] = lca; 97 } 98 s[++top] = x; 99 } 100 101 inline int comp(const int &a, const int &b) 102 { 103 return dfn[a] < dfn[b]; 104 } 105 106 vector<int>mmp[maxn]; 107 108 int main() 109 { 110 int n,x,m; 111 memset(answer,-1, sizeof(answer)); 112 memset(frist, -1, sizeof(frist)); 113 scanf("%d",&n); 114 for(int i=2; i<=n; i++) 115 { 116 scanf("%d",&x); 117 AddEdge(x,i); 118 } 119 120 deep[1]=fa[0][1]=1; 121 dfs(1); 122 for(int i=1;i<=17;i++) 123 for(int j=1;j<=n;j++) 124 fa[i][j]=fa[i-1][fa[i-1][j]]; 125 126 ///将节点存入它权值因子的vector 127 int Max = 0; 128 for(int i=1; i<=n; i++) 129 { 130 scanf("%d",&x); 131 Max = max(Max,x); 132 int temp = sqrt(x+1); 133 for(int j=1; j<=temp; j++) 134 { 135 if(x%j==0) 136 { 137 mmp[j].push_back(i); 138 if(j!=x/j) 139 mmp[x/j].push_back(i); 140 } 141 } 142 } 143 144 for(int k=1; k<=Max; k++) 145 { 146 m = mmp[k].size(); 147 if(m<=1)continue; 148 for(int i = 1; i <= m; i++)a[i] = mmp[k][i-1]; 149 sort(a + 1, a + m + 1, comp); 150 //memset(first2,-1,sizeof(first2)); 151 top=0; 152 for(int i = 1; i <= m; i++) 153 insert_point(a[i],k); 154 while(top > 1) 155 { 156 answer[s[top - 1]]=k; ///不建边了,直接更新答案 157 //add_edge(s[top - 1], s[top]); 158 top--; 159 } 160 //dfs(s[top]); ///省去dfs 161 } 162 for(int i=1;i<=n;i++) 163 printf("%d\n",answer[i]); 164 return 0; 165 }