Advertisement
erek1e

IOI '20 - Tickets (41pts)

Mar 5th, 2023
604
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.74 KB | None | 0 0
  1. #include "tickets.h"
  2. #include <vector>
  3. #include <algorithm>
  4. #include <iostream>
  5.  
  6. using namespace std;
  7.  
  8. const long long INF = 1e18;
  9.  
  10. long long find_maximum(int k, vector<vector<int>> x) {
  11.     int n = x.size();
  12.     int m = x[0].size();
  13.  
  14.     vector<vector<int>> answer(n, vector<int>(m, -1));
  15.     long long prize = 0;
  16.  
  17.     int MAX = 0;
  18.     for (int i = 0; i < n; ++i) {
  19.         for (int j = 0; j < n; ++j) {
  20.             MAX = max(MAX, x[i][j]);
  21.         }
  22.     }
  23.  
  24.     if (k == 1) {
  25.         vector<vector<long long>> dp(1+n, vector<long long>(1+n/2, -INF));
  26.         dp[0][0] = 0;
  27.         // dp on prefix and number of positives
  28.         vector<vector<bool>> chosePositive(1+n, vector<bool>(1+n/2));
  29.         // chosePositive allows backtracking
  30.         for (int i = 0; i < n; ++i) {
  31.             for (int pos = 0; 2*pos <= n; ++pos) {
  32.                 if (dp[i][pos] == -INF) continue;
  33.  
  34.                 // do not choose positive
  35.                 long long v = dp[i][pos] - x[i].front();
  36.                 if (v > dp[i+1][pos]) {
  37.                     dp[i+1][pos] = v;
  38.                     chosePositive[i+1][pos] = false;
  39.                 }
  40.  
  41.                 // choose positive (if possible)
  42.                 if (2*pos == n) continue; // no more positives
  43.                 v = dp[i][pos] + x[i].back();
  44.                 if (v > dp[i+1][pos+1]) {
  45.                     dp[i+1][pos+1] = v;
  46.                     chosePositive[i+1][pos+1] = true;
  47.                 }
  48.             }
  49.         }
  50.  
  51.         prize = dp[n][n>>1];
  52.         // Now reconstruct answer
  53.         for (int i = n, pos = n>>1; i >= 1; --i) {
  54.             if (!chosePositive[i][pos]) answer[i-1][0] = 0;
  55.             else answer[i-1][m-1] = 0, pos--;
  56.         }
  57.     } else if (m == k || MAX == 1) {
  58.         vector<int> cnt[2], remain[2];
  59.         cnt[0].resize(n), cnt[1].resize(n);
  60.         remain[0].resize(n), remain[1].resize(n);
  61.  
  62.         vector<pair<int, int>> v;
  63.         for (int i = 0; i < n; ++i) {
  64.             for (int j = 0; j < m; ++j) v.emplace_back(x[i][j], i);
  65.         }
  66.         sort(v.begin(), v.end());
  67.         for (int i = 0; (i<<1) < n*m; ++i) {
  68.             ++cnt[0][v[i].second];
  69.         }
  70.         for (int i = 0; i < n; ++i) {
  71.             cnt[1][i] = m-cnt[0][i];
  72.             remain[0][i] = cnt[0][i];
  73.             remain[1][i] = cnt[1][i];
  74.         }
  75.  
  76.         for (int i = 0; i < k; ++i) {
  77.             int used0 = 0;
  78.             for (int y = 0; y < n; ++y) {
  79.                 if (!remain[1][y]) { // zero
  80.                     prize -= x[y][cnt[0][y]-remain[0][y]];
  81.                     answer[y][cnt[0][y]-remain[0][y]] = i;
  82.                     --remain[0][y];
  83.                     ++used0;
  84.                 } else if (!remain[0][y]) { // one
  85.                     prize += x[y][cnt[0][y]+remain[1][y]-1];
  86.                     answer[y][cnt[0][y]+remain[1][y]-1] = i;
  87.                     --remain[1][y];
  88.                 }
  89.             }
  90.             for (int y = 0; y < n; ++y) { // both
  91.                 if (!remain[0][y] || !remain[1][y]) continue;
  92.                 if (2*used0 < n) {
  93.                     prize -= x[y][cnt[0][y]-remain[0][y]];
  94.                     answer[y][cnt[0][y]-remain[0][y]] = i;
  95.                     --remain[0][y];
  96.                     ++used0;
  97.                 } else {
  98.                     prize += x[y][cnt[0][y]+remain[1][y]-1];
  99.                     answer[y][cnt[0][y]+remain[1][y]-1] = i;
  100.                     --remain[1][y];
  101.                 }
  102.             }
  103.         }
  104.     }
  105.     allocate_tickets(answer);
  106.     return prize;
  107. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement