Submission #1361654

#TimeUsernameProblemLanguageResultExecution timeMemory
1361654altern23Catfish Farm (IOI22_fish)C++20
100 / 100
147 ms70112 KiB
#include "fish.h"

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const ll INF = 1e18;

long long max_weights(int N, int M, vector<int> X, vector<int> Y, vector<int> W) {
      vector <pair<ll, ll>> points[N+5];

      for (int i = 0; i < M; i++) {
            X[i]++, Y[i]++;

            points[X[i]].push_back({Y[i], W[i]});

            if (X[i]+1 <= N) {
                  points[X[i]+1].push_back({Y[i], 0});
            }
      }

      for (int i = 0; i <= N; i++) {
            points[i].push_back({0, 0});
      }

      for (int i = 1; i <= N; i++) {
            sort(points[i].begin(), points[i].end());

            // compress these points
            vector <pair<ll, ll>> tmp;

            for (auto [x, y] : points[i]) {
                  if (!tmp.size()) tmp.push_back({x, y});
                  else if (tmp.back().first == x) tmp.back().second += y;
                  else tmp.push_back({x, y});
            }

            points[i].swap(tmp);
      }

      vector <vector<vector<ll>>> dp(N+5, vector <vector<ll>> (2));
      vector <vector<ll>> ps(N+5), sf(N+5);
      vector <ll> MX(N+5, -INF);

      for (int i = 0; i <= N; i++) {
            dp[i][0].resize(points[i].size()+1, -INF), dp[i][1].resize(points[i].size()+1, -INF);
            ps[i].resize(points[i].size()+1, -INF), sf[i].resize(points[i].size()+1, -INF);

            for (int j = 1; j < (ll)points[i].size(); j++) {
                  points[i][j].second += points[i][j-1].second;
            }
      }

      dp[0][0][0] = 0;

      ll ans = 0;

      for (int i = 0; i <= N; i++) {
            if (i) {
                  for (int j = 0; j < (ll)points[i-1].size(); j++) {
                        dp[i][0][0] = max(dp[i][0][0], dp[i-1][0][j]);
                        dp[i][0][0] = max(dp[i][0][0], dp[i-1][1][j]);
                  }

                  for (int j = 1; j < (ll)points[i].size(); j++) {
                        if (i < N) {
                              // increasing
                              dp[i][0][j] = max(dp[i][0][j], ps[i][j-1] + points[i][j].second);
                              dp[i][0][j] = max(dp[i][0][j], MX[i-1] + points[i][j].second);
                        }
                        if (i > 1) {
                              // decreasing
                              dp[i][1][j] = max(dp[i][1][j], sf[i][j+1] - points[i][j-1].second);
                              dp[i][1][j] = max(dp[i][1][j], dp[i-1][0][0] + (points[i].back().second-points[i][j-1].second));
                        }
                        
                        ans = max({ans, dp[i][0][j], dp[i][1][j]});
                        MX[i] = max(MX[i], dp[i][1][j]);
                  }
            }

            if (i+1 <= N) {
                  ps[i+1][0] = dp[i][0][0];

                  ll ptr = 0;
                  for (int j = 1; j < (ll)points[i+1].size(); j++) {
                        ps[i+1][j] = ps[i+1][j-1];
                        while (ptr < (ll)points[i].size() && points[i][ptr].first < points[i+1][j].first) ptr++;
                        if (ptr < points[i].size() && points[i][ptr].first == points[i+1][j].first) {
                              ps[i+1][j] = max(ps[i+1][j], dp[i][0][ptr] - points[i+1][j].second);
                        }
                  }

                  ptr = points[i].size()-1;

                  for (int j = points[i+1].size()-1; j >= 0; --j) {
                        sf[i+1][j] = sf[i+1][j+1];
                        while (ptr >= 0 && points[i][ptr].first > points[i+1][j].first) ptr--;
                        if (ptr >= 0 && points[i][ptr].first == points[i+1][j].first) {
                              sf[i+1][j] = max(sf[i+1][j], dp[i][1][ptr] + (j == 0 ? 0LL : points[i+1][j-1].second));
                        }
                  }
            }
      }

      return ans;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...