Advertisement
erek1e

POI Task Distance

Jul 11th, 2022
929
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.58 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4.  
  5. using namespace std;
  6.  
  7. /* This version of the code is adapted with modified precomputation
  8.  - only precomputing up to necessary max for specific testcase
  9.  This is because there are some small tests with low time limits */
  10.  
  11. int main() {
  12.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  13.  
  14.     int n, mx = 0; cin >> n;
  15.     vector<int> a(n);
  16.     for (int &x : a) cin >> x, mx = max(mx, x);
  17.  
  18.     vector<int> smallestFactor(1+mx); // smallest prime factor
  19.     vector<vector<int>> pos(1+mx); // list of positions in the array of each value up to MX
  20.     vector<bool> got(1+mx);
  21.  
  22.     // Sieve of Eratosthenes
  23.     for (int i = 2; i <= mx; ++i) {
  24.         if (smallestFactor[i]) continue;
  25.         smallestFactor[i] = i;
  26.         for (long long j = (long long)i*i; j <= mx; j += i) {
  27.             if (!smallestFactor[j] || smallestFactor[j] > i) smallestFactor[j] = i;
  28.         }
  29.     }
  30.  
  31.     auto getF = [&smallestFactor](int x) { // sum of powers of prime factors
  32.         int f = 0;
  33.         while (smallestFactor[x]) {
  34.             x /= smallestFactor[x];
  35.             ++f;
  36.         }
  37.         return f;
  38.     };
  39.  
  40.     vector<int> f(n);
  41.     for (int i = 0; i < n; ++i) {
  42.         pos[a[i]].push_back(i);
  43.         got[a[i]] = true;
  44.         f[i] = getF(a[i]);
  45.     }
  46.  
  47.     vector<int> ans(n, -1), ansDist(n, -1);
  48.  
  49.     auto lowerF = [&f](int i, int j) {
  50.         return j == -1 || f[i] < f[j] || (f[i] == f[j] && i < j);
  51.     };
  52.  
  53.     // go through all divisors (will be gcd in each final answer)
  54.     for (int d = 1; d <= mx; ++d) {
  55.         int fd = getF(d);
  56.  
  57.         // consider all multiples of d in the array
  58.         int small = -1, next = -1; // smallest, next smallest
  59.         for (int m = d; m <= mx; m += d) {
  60.             if (!got[m]) continue;
  61.             for (int i : pos[m]) {
  62.                 if (lowerF(i, next)) {
  63.                     next = i;
  64.                     if (lowerF(next, small)) swap(small, next);
  65.                 }
  66.             }
  67.         }
  68.  
  69.         for (int m = d; m <= mx; m += d) {
  70.             if (!got[m]) continue;
  71.             for (int i : pos[m]) {
  72.                 int cur = small;
  73.                 if (i == small) {
  74.                     if (next == -1) continue;
  75.                     cur = next;
  76.                 }
  77.                 int dist = f[i] + f[cur] - 2*fd;
  78.  
  79.                 if (ans[i] == -1 || dist < ansDist[i] || (dist == ansDist[i] && cur < ans[i])) ans[i] = cur, ansDist[i] = dist;
  80.             }
  81.         }
  82.     }
  83.  
  84.     for (int i = 0; i < n; ++i) cout << ans[i]+1 << endl;
  85.     return 0;
  86. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement