Submission #1184109

#TimeUsernameProblemLanguageResultExecution timeMemory
1184109SwanCatfish Farm (IOI22_fish)C++20
100 / 100
299 ms49248 KiB
#pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #include <iostream> #include <vector> #include <stack> #include <algorithm> #include <string> #include <set> #include <map> #include <list> #include <time.h> #include <math.h> #include <random> #include <deque> #include <queue> #include <cassert> #include <climits> #include <unordered_map> #include <unordered_set> #include <iomanip> #include <bitset> #include <sstream> #include <chrono> #include <cstring> #include <optional> //#define int long long #define INP freopen("subrev.in","r",stdin) #define OUTP freopen("subrev.out","w",stdout) using ld = long double; using LD = ld; using namespace std; const int maxn = 3e5 + 123; struct st { int y = 0; long long val = 0; long long pointsBelow = 0; st() {} st (int y, long long val, long long pointsBelow) : y(y), val(val), pointsBelow(pointsBelow) {} bool operator< (const st& ot) const { return y < ot.y; } bool operator< (const int val) const { return y < val; } friend bool operator<(const int& val, const st& ot) { return val < ot.y; } }; vector<st> points[maxn]; vector<long long> prefSum[maxn]; long long getSum(int col, int y) { if (col < 0) return 0; long long ans = 0; int num = upper_bound(points[col].begin(), points[col].end(), y) - points[col].begin(); if (num == points[col].size()) num--; while (num > -1 && points[col][num].y > y) num--; if (num == -1) { return 0; } return prefSum[col][num]; } long long solve(vector<st>& prevRise, vector<st>& prevDown, vector<st>& prevNoPiles, vector<st>& curRise, vector<st>& curDown, vector<st>& curNoPiles, vector<int>& interestingPoints, int curx) { int prevDownPointer = -1; int prevRisePointer = -1; int prevNoPilesPointer = -1; long long bestDown = 0; long long bestRise = 0; long long bestNoPiles = 0; long long bestNoPilesHigher = 0; long long overallMax = 0; for (auto a : prevNoPiles) bestNoPilesHigher = max(bestNoPilesHigher, a.val); for (int i = 0; i < interestingPoints.size(); i++) { while (prevRisePointer + 1 < prevRise.size() && prevRise[prevRisePointer + 1].y < interestingPoints[i]) { prevRisePointer++; bestDown = max(bestDown, prevRise[prevRisePointer].val - prevRise[prevRisePointer].pointsBelow); } while (prevNoPilesPointer + 1 < prevNoPiles.size() && prevNoPiles[prevNoPilesPointer + 1].y <= interestingPoints[i]) { prevNoPilesPointer++; bestNoPiles = max(bestNoPiles, prevNoPiles[prevNoPilesPointer].val - prevNoPiles[prevNoPilesPointer].pointsBelow); } long long numberOfPoints = 0; long long numberOfPointsNow = 0; if (curx) { numberOfPoints = getSum(curx - 1, interestingPoints[i]); } numberOfPointsNow = getSum(curx, interestingPoints[i]); long long ans = bestNoPilesHigher; ans = max(ans, numberOfPoints + max(bestDown, bestNoPiles)); curRise.push_back({interestingPoints[i], ans , numberOfPointsNow}); } prevDownPointer = prevDown.size(); prevRisePointer = prevRise.size(); bestDown = 0; bestRise = 0; bestNoPiles = 0; // << interestingPoints.size() << endl; for (int i = interestingPoints.size() - 1; i >= 0; i--) { while (prevRisePointer - 1 >= 0 && prevRise[prevRisePointer - 1].y >= interestingPoints[i]) { prevRisePointer--; long long numberOfPointsNowSum = getSum(curx, prevRise[prevRisePointer].y); bestRise = max(bestRise, prevRise[prevRisePointer].val + numberOfPointsNowSum); bestNoPiles = max(bestNoPiles, prevRise[prevRisePointer].val); //if (curx == 4) cout << bestRise << endl; } while (prevDownPointer - 1 >= 0 && prevDown[prevDownPointer - 1].y >= interestingPoints[i]) { prevDownPointer--; long long numberOfPointsNowSum = getSum(curx, prevDown[prevDownPointer].y); bestDown = max(bestDown, prevDown[prevDownPointer].val + numberOfPointsNowSum); bestNoPiles = max(bestNoPiles, prevDown[prevDownPointer].val); } long long numberOfPointsNow = getSum(curx, interestingPoints[i]); long long ans = max(bestDown, bestRise) - numberOfPointsNow; ans = max(ans, 0ll); curDown.push_back({interestingPoints[i], ans , numberOfPointsNow}); if (prevDownPointer == prevDown.size() && prevRisePointer == prevRise.size()) ans = 0; else ans = bestNoPiles + numberOfPointsNow; curNoPiles.push_back({interestingPoints[i], ans, numberOfPointsNow}); } reverse(curDown.begin(), curDown.end()); for (auto a : prevDown) overallMax = max(overallMax, a.val); for (auto a : prevRise) overallMax = max(overallMax, a.val); for (auto a : prevNoPiles) overallMax = max(overallMax, a.val); //cout << "OVERALL " << curx << ' ' << curNoPiles[0].val << endl; curNoPiles.push_back({-1, overallMax, 0}); reverse(curNoPiles.begin(), curNoPiles.end()); return overallMax; } long long max_weights(int N, int M, vector<int> X, vector<int> Y, vector<int> W) { for (int i = 0; i < M; i++) { points[X[i]].push_back(st({Y[i], W[i], 0})); } for (int i = 0; i < N; i++) { sort(points[i].begin(), points[i].end()); for (int j = 0; j < points[i].size(); j++) { points[i][j].pointsBelow = j; prefSum[i].push_back(points[i][j].val); if (j) prefSum[i][j] += prefSum[i][j - 1]; } } vector<st> prevRise; vector<st> prevDown; vector<st> prevNoPiles; vector<st> curRise; vector<st> curDown; vector<st> curNoPiles; long long ans = 0; curNoPiles.push_back({-1, 0, 0}); for (int i = 0; i < N; i++) { swap(prevRise, curRise); swap(prevDown, curDown); swap(prevNoPiles, curNoPiles); curRise.clear(); curDown.clear(); curNoPiles.clear(); vector<int> interestingPointsUnsorted; vector<int> interestingPoints; if (i) { for (auto a : points[i - 1]) interestingPointsUnsorted.push_back(a.y); } for (auto a : points[i]) interestingPointsUnsorted.push_back(a.y); if (i + 1 < N) { for (auto a : points[i + 1]) interestingPointsUnsorted.push_back(a.y); } sort(interestingPointsUnsorted.begin(), interestingPointsUnsorted.end()); for (int i = 0; i < interestingPointsUnsorted.size(); i++) { if (i == interestingPointsUnsorted.size() - 1) { interestingPoints.push_back(interestingPointsUnsorted[i]); continue; } if (interestingPointsUnsorted[i] != interestingPointsUnsorted[i + 1]) { interestingPoints.push_back(interestingPointsUnsorted[i]); } } ans = max(ans, solve(prevRise, prevDown, prevNoPiles, curRise, curDown, curNoPiles, interestingPoints, i)); } for (auto a : curDown) { ans = max(ans, a.val); } for (auto a : curRise) { ans = max(ans, a.val); } for (auto a : curNoPiles) { ans = max(ans, a.val); } return ans; } /* void solve() { int n, m; cin >> n >> m; vector<int> X, Y, W; for (int i = 0; i < m; i++) { int x, y, w; cin >> x >> y >> w; X.push_back(x); Y.push_back(y); W.push_back(w); } cout << max_weights(n, m, X, Y, W); // 5, 4, [0, 1, 4, 3], [2, 1, 4, 3], [5, 2, 1, 3] //cout << max_weights(5, 4, {0, 1, 4, 3}, {2, 1, 4, 3}, {5, 2, 1, 3}) << endl; //cout << max_weights(10000, 1, {0}, {0}, {10082010}) << endl; // cout << max_weights(4, 3, {2, 0, 1}, {2, 0, 1}, {1, 1, 1}); //cout << max_weights(8, 7, {5, 4, 6, 3, 0, 2, 1}, {5, 4, 6, 3, 0, 2, 1}, {1, 1, 1, 1, 1, 1, 1}); // cout << max_weights(5, 3, {1, 2, 3}, {0,0, 0}, {1, 1, 1}); //cout << max_weights(7, 7, {0, 1, 2, 3, 4, 5, 6}, {0, 0, 0, 0, 0, 0, 0}, {1, 2, 3, 4, 5, 6, 7}); } int main() { ios_base::sync_with_stdio(0); solve(); } */
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...