Submission #1122704

#TimeUsernameProblemLanguageResultExecution timeMemory
1122704NonozeCatfish Farm (IOI22_fish)C++20
100 / 100
462 ms230924 KiB
#include "fish.h"

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

#ifndef _IN_LOCAL
	#define dbg(...)
#endif

#define endl '\n'
#define endlfl '\n' << flush
#define quit(x) return (void)(cout << x << endl)

template<typename T> void read(T& x) { cin >> x;}
template<typename T1, typename T2> void read(pair<T1, T2>& p) { read(p.first), read(p.second);}
template<typename T> void read(vector<T>& v) { for (auto& x : v) read(x); }
template<typename T1, typename T2> void read(T1& x, T2& y) { read(x), read(y); }
template<typename T1, typename T2, typename T3> void read(T1& x, T2& y, T3& z) { read(x), read(y), read(z); }
template<typename T1, typename T2, typename T3, typename T4> void read(T1& x, T2& y, T3& z, T4& zz) { read(x), read(y), read(z), read(zz); }
template<typename T> void print(vector<T>& v) { for (auto& x : v) cout << x << ' '; cout << endl; }

#define sz(x) (int)(x.size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define pb push_back
#define mp(a, b) make_pair(a, b)
#define fi first
#define se second
#define cmin(a, b) a = min(a, b)
#define cmax(a, b) a = max(a, b)
#define YES cout << "YES" << endl
#define NO cout << "NO" << endl
#define QYES quit("YES")
#define QNO quit("NO")

#define int long long
#define double long double
const int inf = numeric_limits<int>::max() / 4;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int MOD = 1e9+7, LOG=20;



int n;
vector<vector<pair<int, int>>> pref, is;
vector<vector<int>> memo;
vector<vector<vector<int>>> lbs, lbs2;

int lowb(int x, int y, int j) {
	y+=2;
	if (y>1) y--;
	return lbs[x][y][j];
}

int calc(int i, int y, int j) {
	if (i>=n || i<0) return 0;
	y+=2; if (y>1) y--;
	return lbs2[i][y][j];
}


int dp(int i, int j, int nb, bool before, bool taking) {
	if (nb>=3 || i>=n) return 0;
	if (memo[i][j*12+nb*4+before*2+taking]!=-1) return memo[i][j*12+nb*4+before*2+taking];
	int ans=0;
	if (taking) {
		if (nb==2) {
			cmax(ans, dp(i+1, j, 0, 0, 0) + calc(i-1, 1, j) + calc(i+1, -1, j));
			if (j+1<sz(is[i])) cmax(ans, dp(i, j+1, 2, 0, 1));
		} else if (nb==1) {
			cmax(ans, dp(i+1, j, 0, 0, 0) + calc(i+1, -1, j));
			if (before && j) cmax(ans, dp(i, j-1, 1, 1, 1));
			else if (!before && j+1<sz(is[i])) cmax(ans, dp(i, j+1, 1, 0, 1) + calc(i-1, 1, j+1) - calc(i-1, 1, j));
		} else {
			if (i+1<n) {
				int res=dp(i+2, j, 1, 0, 0);
				int empl=lowb(i+1, -1, j), clc=pref[i+1][empl].se-is[i+1][empl].se;
				if (!before) cmax(res, dp(i+1, empl, 1, 0, 1) - clc + calc(i, 1, empl) - (j?pref[i][j-1].se:0));
				if (empl) cmax(res, dp(i+1, empl-1, 0, 1, 1) + is[i+1][empl-1].se - clc);

				cmax(ans, res + calc(i+1, -1, j));
			}
			
			if (before && j) cmax(ans, dp(i, j-1, 0, 1, 1)+is[i][j-1].se);
			else if (!before && j+1<sz(is[i])) cmax(ans, dp(i, j+1, 0, 0, 1) + calc(i-1, 1, j+1) - calc(i-1, 1, j));
		}
	} else {
		cmax(ans, dp(i+1, j, nb+1, 0, 0));
		if (nb==0) {
			int empl=lowb(i, -1, j), clc=pref[i][empl].se-is[i][empl].se;
			cmax(ans, dp(i, empl, 0, 0, 1) - clc + calc(i-1, 1, empl) - (j?pref[i-1][j-1].se:0));
			if (empl) cmax(ans, dp(i, empl-1, 0, 1, 1) + is[i][empl-1].se - clc);

		} else if (nb==1) {
			int empl=0;
			if (i-2>=0) empl=lowb(i, -2, j);
			cmax(ans, dp(i, empl, 1, 0, 1));
			if (empl) cmax(ans, dp(i, empl-1, 1, 1, 1));
		} else {
			cmax(ans, dp(i, 0, nb, 0, 1));
		}
	}
	return memo[i][j*12+nb*4+before*2+taking]=ans;
}


int max_weights(signed N, signed m, vector<signed> x, vector<signed> y, vector<signed> w) {
	n=N;
	pref.resize(n), is.resize(n), memo.resize(n);
	for (int i=0; i<m; i++) {
		is[x[i]].pb({y[i], w[i]});
	}
	for (int i=0; i<n; i++) {
		sort(all(is[i]));
		is[i].pb({n, 0});
		int sm=0;
		for (auto [j, x]: is[i]) {
			sm+=x;
			pref[i].pb({j, sm});
		}
	}

	lbs.resize(n, vector<vector<int>>(3));
	lbs2.resize(n, vector<vector<int>>(3));
	for (int y=-2; y<=1; y++) {
		if (y==0) continue;
		int valy=y+2;
		if (valy>1) valy--;
		for (int i=0; i<n; i++) {
			if (i+y<0 || i+y>=n) continue;
			int empl=0;
			lbs[i][valy].resize(sz(is[i+y])), lbs2[i][valy].resize(sz(is[i+y]));
			for (int j=0; j<sz(is[i+y]); j++) {

				lbs[i][valy][j]=lower_bound(all(is[i]), mp(is[i+y][j].fi, 0LL))-is[i].begin();
				int val=lbs[i][valy][j];
				while (val>=0 && is[i][val].fi>=is[i+y][j].fi) val--;
				lbs2[i][valy][j]=(val>=0?pref[i][val].se:0);
			}
		}
	}

	for (int i=0; i<n; i++) {
		if (sz(memo[i])<sz(is[i])*12) memo[i].resize(sz(is[i])*12, -1);
		if (i+1<n && sz(memo[i+1])<sz(is[i])*12) memo[i+1].resize(sz(is[i])*12, -1);
		if (i+2<n && sz(memo[i+2])<sz(is[i])*12) memo[i+2].resize(sz(is[i])*12, -1);
		if (i+3<n && sz(memo[i+3])<sz(is[i])*12) memo[i+3].resize(sz(is[i])*12, -1);
	}
	return dp(0, 0, 1, 0, 0);
}
#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...