Advertisement
RaFiN_

cf 463E

Aug 19th, 2019
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.96 KB | None | 0 0
  1. /* cf 463E */
  2.  
  3. /*I'll post my solution for E and try to do a "mini-editorial" for it. You can easily notice that the value for any node is maximum 2*10^6. We can keep a binary search tree (Set in c++) for every number from 1 to 2*10^6. In each set we will keep a pair (depth[node], node) in order to find in O(1) the deepest node which has the divisor according to the set.
  4.  
  5. Example: node = 1; value[node] = 6; ( 6 = 2*3 ) depth[node] = 2;
  6.  
  7. At one point we will have: (2,1) in Set[2] and
  8.                   (2,1) in Set[3]
  9. We modify these sets in the DFS as follows:
  10.  
  11. void DFS (int node)
  12. {
  13.     ans[node] = pair(-1,-1) /// we might not have an answer for this node
  14.  
  15.     for ( every prime divisor of value[node] )
  16.         if ( Set[ prime divisor] not empty ) /// we have found a node x that has the same divisor and our node
  17.         ans[node] = max( ans[node], last_element_in_set );
  18.  
  19.     for ( every prime divisor of value[node] )
  20.         Set[ prime divisor ].insert( pair( depth[node], node ) );
  21.  
  22.     for ( every every child of node )
  23.         DFS(child)
  24.  
  25.     for ( every prime divisor of value[node] )
  26.         Set[ prime divisor ].erase( pair( depth[node], node ) );
  27. }
  28. !!!Node: these sets are gives the nodes sorted by their depth
  29.  
  30. When we find an update query we just run DFS(1) and done! If something is not clear just ask!*/
  31.  
  32. int prime[MAX],p,arr[MAX];vi Div[MAX];pii ans[MAX];
  33. set<pii>S[MAX];vi v[MAX];
  34. void sieve(int n){
  35.     double z = sqrt(n);
  36.     for(int i = 3;i<=z;i+=2){
  37.         if(!arr[i]){
  38.             for(ll j = (i*i);j<=n;j+=i+i)arr[j] = 1;
  39.         }
  40.     }
  41.     prime[p++] = 2;
  42.     for(int i = 3;i<=n;i+=2)if(!arr[i])prime[p++] = i;
  43. }
  44.  
  45. void fact(int n){
  46.     int root = n;
  47.     Div[root].clear();
  48.     for(int i = 0;prime[i]*prime[i]<=n;i++){
  49.         if(n%prime[i]==0){
  50.             Div[root].pb(prime[i]);
  51.             while(n%prime[i]==0)n/=prime[i];
  52.         }
  53.     }
  54.     if(n>1)Div[root].pb(n);
  55. }
  56.  
  57. void dfs(int n,int depth,int p = 0){
  58.     ans[n] = {-1,-1};
  59.     for(auto it : Div[arr[n]]){
  60.         if((int)S[it].size()!=0){
  61.             ans[n] = max(ans[n],*S[it].rbegin());
  62.         }
  63.     }
  64.     for(auto it : Div[arr[n]]){
  65.         S[it].insert({depth,n});
  66.     }
  67.     for(auto it : v[n]){
  68.         if(it!=p)dfs(it,depth+1,n);
  69.     }
  70.     for(auto it : Div[arr[n]]){
  71.         S[it].erase({depth,n});
  72.     }
  73. }
  74.  
  75. int main()
  76. {
  77.     booster()
  78.    // read("input.txt");
  79.     sieve(2000000);
  80.     int n,q;
  81.     cin>>n>>q;
  82.     for(int i = 1;i<=n;i++){
  83.         cin>>arr[i];
  84.         fact(arr[i]);
  85.     }
  86.     for(int i = 0;i<n-1;i++){
  87.         int a,b;
  88.         cin>>a>>b;
  89.         v[a].pb(b);
  90.         v[b].pb(a);
  91.     }
  92.  
  93.     dfs(1,0);
  94.     for(int i = 1;i<=q;i++){
  95.         int a;
  96.         cin>>a;
  97.         if(a==1){
  98.             int node;
  99.             cin>>node;
  100.             cout<<ans[node].ss<<endl;
  101.         }
  102.         else {
  103.             int node,val;
  104.             cin>>node>>val;
  105.             arr[node] = val;
  106.             fact(val);
  107.             dfs(1,0);
  108.         }
  109.     }
  110.  
  111.     return 0;
  112. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement