Advertisement
erek1e

EGOI '23 - Padel Prize Pursuit

Jul 21st, 2023
745
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.22 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. // Fenwick
  6. void update(vector<int> &fenwick, int index, int value) {
  7.     while (index < (int)fenwick.size()) {
  8.         fenwick[index] += value;
  9.         index += index & -index;
  10.     }
  11. }
  12. int getSum(vector<int> &fenwick, int index) {
  13.     int sum = 0;
  14.     while (index) {
  15.         sum += fenwick[index];
  16.         index -= index & -index;
  17.     }
  18.     return sum;
  19. }
  20. // using fenwick with range update, point query
  21.  
  22. tuple<vector<int>, vector<int>, vector<int>> get_DFS_order(const vector<vector<int>> &children) {
  23.     int m = (int)children.size()-1;
  24.     vector<int> tin(m+1), tout(m+1), depth(m+1);
  25.     int t = 0;
  26.     function<void(int, int)> dfs = [&](int node, int d) {
  27.         depth[node] = d;
  28.         tin[node] = t++;
  29.         for (int child : children[node]) dfs(child, d+1);
  30.         tout[node] = t;
  31.     };
  32.     dfs(m, 0);
  33.  
  34.     return {tin, tout, depth};
  35. }
  36.  
  37. int main() {
  38.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  39.     int n, m; cin >> n >> m;
  40.     vector<int> x(m), y(m);
  41.     for (int i = 0; i < m; ++i) cin >> x[i] >> y[i];
  42.    
  43.     // precalculate winBackMoment
  44.     //  - first moment after t that the initial winner of medal t wins medal t back
  45.     vector<int> winBackMoment(m);
  46.     {
  47.         // create rooted tree with every node i being linked upwards to the next time x[i] is beaten
  48.         vector<vector<int>> children(1+m);
  49.         vector<int> nextLoss(n, m);
  50.         for (int i = m-1; i >= 0; --i) {
  51.             children[nextLoss[x[i]]].push_back(i);
  52.             nextLoss[y[i]] = i;
  53.         }
  54.  
  55.         // generate dfs order for this tree, root being at m
  56.         tuple<vector<int>, vector<int>, vector<int>> triple = get_DFS_order(children);
  57.         vector<int> tin = get<0>(triple), tout = get<1>(triple), depth = get<2>(triple);
  58.  
  59.         // for each node i, find winBackMoment: nearest ancestor j such that x[i] == x[j]
  60.         vector<vector<int>> iWithX(n);
  61.         for (int i = 0; i < m; ++i) iWithX[x[i]].push_back(i);
  62.  
  63.  
  64.         vector<int> fenwick(1+m+10); // indexed by tin and tout
  65.         update(fenwick, 1, m); // all answers initially m
  66.         for (int X = 0; X < n; ++X) { // find winBackMoment for all i with this x
  67.             // sort by depth
  68.             sort(iWithX[X].begin(), iWithX[X].end(), [&depth](int i, int j){
  69.                 return depth[i] < depth[j];
  70.             });
  71.             vector<pair<int, int>> pastUpdates;
  72.             for (int i : iWithX[X]) {
  73.                 // read fenwick at tin[i] for ans i
  74.                 int ancestor = getSum(fenwick, tin[i]);
  75.                 winBackMoment[i] = ancestor;
  76.                 // update fenwick by setting [tin[i], tout[i]) to i
  77.                 // but all values on that range are currently == ancestor, so just add i-ancestor
  78.                 update(fenwick, tin[i], i-ancestor); // tin and tout always positive since root (m) has tin 0
  79.                 update(fenwick, tout[i], ancestor-i);
  80.                 pastUpdates.emplace_back(tin[i], i-ancestor);
  81.                 pastUpdates.emplace_back(tout[i], ancestor-i);
  82.             }
  83.             while (!pastUpdates.empty()) {
  84.                 auto [i, v] = pastUpdates.back();
  85.                 update(fenwick, i, -v);
  86.                 pastUpdates.pop_back();
  87.             }
  88.         }
  89.     }
  90.    
  91.  
  92.     vector<int> timeKeptByWinner(m); // time spent by winner of match i with the medal won at that time
  93.  
  94.     vector<pair<int, int>> medalWinner(1+m, {0, 0}); // time, -person
  95.     vector<int> nextLoss(n, m);
  96.     for (int t = m-1; t >= 0; --t) {
  97.         int i = x[t], j = y[t]; // i beat j at time t
  98.  
  99.         // how much time does i spend with medal t after this point?
  100.         //  - initial time before losing
  101.         timeKeptByWinner[t] = nextLoss[i]-t;
  102.         //  - possible time later after winning it back
  103.         if (winBackMoment[t] < m) timeKeptByWinner[t] += timeKeptByWinner[winBackMoment[t]];
  104.  
  105.         medalWinner[t] = max(medalWinner[nextLoss[i]], {timeKeptByWinner[t], -i});
  106.  
  107.         // update nextLoss
  108.         nextLoss[j] = t;
  109.     }
  110.  
  111.     vector<int> medalsWon(n);
  112.     for (int i = 0; i < m; ++i) ++medalsWon[-medalWinner[i].second];
  113.     for (int v : medalsWon) cout << v << ' ';
  114.     cout << endl;
  115.     return 0;
  116. }
  117.  
Advertisement
Comments
Add Comment
Please, Sign In to add comment
Advertisement