Submission #758048

#TimeUsernameProblemLanguageResultExecution timeMemory
758048maomao90Tortoise (CEOI21_tortoise)C++17
100 / 100
631 ms37664 KiB
// Hallelujah, praise the one who set me free
// Hallelujah, death has lost its grip on me
// You have broken every chain, There's salvation in your name
// Jesus Christ, my living hope
#include <bits/stdc++.h> 
using namespace std;

#define REP(i, s, e) for (int i = (s); i < (e); i++)
#define RREP(i, s, e) for (int i = (s); i >= (e); i--)
template <class T>
inline bool mnto(T& a, T b) {return a > b ? a = b, 1 : 0;}
template <class T>
inline bool mxto(T& a, T b) {return a < b ? a = b, 1: 0;}
typedef long long ll;
typedef long double ld;
#define FI first
#define SE second
typedef pair<int, int> ii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> iii;
#define ALL(_a) _a.begin(), _a.end()
#define SZ(_a) (int) _a.size()
#define pb push_back
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<ii> vii;
typedef vector<iii> viii;

#ifndef DEBUG
#define cerr if (0) cerr
#endif

const int INF = 1000000005;
const ll LINF = 1000000000000000005ll;
const int MAXN = 500005;

int n;
int a[MAXN];
int lft[MAXN], rht[MAXN];
int grp[MAXN], lstgrp[MAXN], prvgrp[MAXN];
bool done[MAXN], donewalk[MAXN];
ll ans;

int fw[MAXN];
void fincre(int i, int x) {
	i++;
	for (; i <= n; i += i & -i) {
		fw[i] += x;
	}
}
void fincre(int s, int e, int x) {
	fincre(s, x);
	fincre(e + 1, -x);
}
int fqsm(int i) {
	i++;
	int res = 0;
	for (; i > 0; i -= i & -i) {
		res += fw[i];
	}
	return res;
}

#define MLR int mid = lo + hi >> 1, lc = u << 1, rc = u << 1 ^ 1
int st[MAXN * 4], lz[MAXN * 4];
void propo(int u, int lo, int hi) {
	if (lz[u] == 0) {
		return;
	}
	MLR;
	st[lc] += lz[u];
	lz[lc] += lz[u];
	st[rc] += lz[u];
	lz[rc] += lz[u];
	lz[u] = 0;
}
void upd(int p, int x, int u = 1, int lo = 0, int hi = n - 1) {
	if (lo == hi) {
		st[u] = x;
		return;
	}
	MLR;
	propo(u, lo, hi);
	if (p <= mid) {
		upd(p, x, lc, lo, mid);
	} else {
		upd(p, x, rc, mid + 1, hi);
	}
	st[u] = min(st[lc], st[rc]);
}
void incre(int s, int e, int x, int u = 1, int lo = 0, int hi = n - 1) {
	if (s > e) {
		return;
	}
	if (lo >= s && hi <= e) {
		st[u] += x;
		lz[u] += x;
		return;
	}
	MLR;
	propo(u, lo, hi);
	if (s <= mid) {
		incre(s, e, x, lc, lo, mid);
	}
	if (e > mid) {
		incre(s, e, x, rc, mid + 1, hi);
	}
	st[u] = min(st[lc], st[rc]);
}
int qmn(int s, int e, int u = 1, int lo = 0, int hi = n - 1) {
	if (s > e) {
		return INF;
	}
	if (lo >= s && hi <= e) {
		return st[u];
	}
	MLR;
	propo(u, lo, hi);
	int res = INF;
	if (s <= mid) {
		mnto(res, qmn(s, e, lc, lo, mid));
	}
	if (e > mid) {
		mnto(res, qmn(s, e, rc, mid + 1, hi));
	}
	return res;
}

ii st2[MAXN * 4];
int lz2[MAXN * 4];
void propo2(int u, int lo, int hi) {
	if (lz2[u] == 0) {
		return;
	}
	MLR;
	st2[lc].FI += lz2[u];
	lz2[lc] += lz2[u];
	st2[rc].FI += lz2[u];
	lz2[rc] += lz2[u];
	lz2[u] = 0;
}
void upd2(int p, int x, int u = 1, int lo = 0, int hi = n - 1) {
	if (lo == hi) {
		st2[u] = {x, lo};
		return;
	}
	MLR;
	propo2(u, lo, hi);
	if (p <= mid) {
		upd2(p, x, lc, lo, mid);
	} else {
		upd2(p, x, rc, mid + 1, hi);
	}
	st2[u] = min(st2[lc], st2[rc]);
}
void incre2(int s, int e, int x, int u = 1, int lo = 0, int hi = n - 1) {
	if (s > e) {
		return;
	}
	if (lo >= s && hi <= e) {
		st2[u].FI += x;
		lz2[u] += x;
		return;
	}
	MLR;
	propo2(u, lo, hi);
	if (s <= mid) {
		incre2(s, e, x, lc, lo, mid);
	}
	if (e > mid) {
		incre2(s, e, x, rc, mid + 1, hi);
	}
	st2[u] = min(st2[lc], st2[rc]);
}
ii qmn2(int s, int e, int u = 1, int lo = 0, int hi = n - 1) {
	if (s > e) {
		return {INF, INF};
	}
	if (lo >= s && hi <= e) {
		return st2[u];
	}
	MLR;
	propo2(u, lo, hi);
	ii res = {INF, INF};
	if (s <= mid) {
		mnto(res, qmn2(s, e, lc, lo, mid));
	}
	if (e > mid) {
		mnto(res, qmn2(s, e, rc, mid + 1, hi));
	}
	return res;
}

int main() {
#ifndef DEBUG
	ios::sync_with_stdio(0), cin.tie(0);
#endif
	cin >> n;
	ll tot = 0;
	REP (i, 0, n) {
		cin >> a[i];
		if (a[i] > 0) {
			tot += a[i];
		}
	}
	int prv = -INF;
	int gc = 0;
	REP (i, 0, n) {
		if (a[i] == -1) {
			prv = i;
			gc++;
		}
		lft[i] = prv;
		grp[i] = gc;
	}
	prv = INF;
	RREP (i, n - 1, 0) {
		if (a[i] == -1) {
			prv = i;
		}
		rht[i] = prv;
	}
	vi id, pos;
	prv = -1;
	REP (i, 0, n) {
		if (a[i] == -1) {
			lstgrp[grp[i] - 1] = prv;
		}
		if (a[i] <= 0) {
			continue;
		}
		id.pb(i);
		pos.pb(i);
		prv = i;
	}
	sort(ALL(id), [&] (int l, int r) {
			return ii{min(l - lft[l], rht[l] - l), -l} < 
			ii{min(r - lft[r], rht[r] - r), -r};
			});
	REP (i, 1, n) {
		fincre(i, n - 1, 1);
	}
	REP (i, 0, n) {
		upd(i, INF);
		upd2(i, INF);
	}
	REP (i, 0, gc + 1) {
		if (lstgrp[i] == -1 || grp[lstgrp[i]] != i) {
			continue;
		}
		upd2(lstgrp[i], lstgrp[i]);
	}
	memset(prvgrp, -1, sizeof prvgrp);
	for (int i : id) {
		cerr << i << '\n';
		done[i] = 1;
		int w = 2 * min(i - lft[i], rht[i] - i);
		// x <= a[i]
		int mn = qmn(i + 1, n - 1);
		assert(mn >= 0);
		// x * w <= mn
		// x <= floor(mn / w)
		int x1 = mn / w;
		int ct = fqsm(i);
		if (ct > 2 * i) {
			continue;
		}
		bool delta = 0;
		if (i - lft[i] <= rht[i] - i) { // left cycle
			if (donewalk[grp[i]]) {
				continue;
			}
			auto apply = [&] (int x, bool walk) {
				if (x + walk == 0) {
					return;
				}
				delta = 1;
				donewalk[grp[i]] |= walk;
				cerr << "APPLY: " << x << ' ' << walk << '\n';
				ans += x + walk;
				fincre(i, n - 1, x * w);
				incre(i, n - 1, -x * w);
				incre2(i, n - 1, -x * w);
				// ct + (x - 1) * w + upd <= 2 * i
				assert(ct + (x - 1 + walk) * w <= 2 * i);
				upd(i, 2 * i - (ct + (x - 1 + walk) * w));
			};
			// ct + (x - 1) * w <= 2 * i
			// x <= (2 * i - ct) / w + 1
			int x2 = (2 * i - ct) / w + 1;
			if (a[i] < min(x1, x2)) {
				auto ptr = upper_bound(ALL(pos), i);
				bool walk = 0;
				if (ptr == pos.end() || grp[*ptr] != grp[i] || done[*ptr]) {
					walk = 1;
				}
				if (donewalk[grp[i]]) {
					walk = 0;
				}
				apply(a[i] - walk, walk);
				if (a[i] + walk) {
					prvgrp[grp[i]] = i;
				}
			} else if (rht[i] == INF) {
				apply(min(x1, x2), 0);
				if (min(x1, x2)) {
					prvgrp[grp[i]] = i;
				}
			} else if (x1 < x2) { // stopped by suffix but still have extra for walk
				auto ptr = upper_bound(ALL(pos), i);
				bool walk = 0;
				if (ptr == pos.end() || grp[*ptr] != grp[i] || done[*ptr]) {
					walk = 1;
				}
				if (donewalk[grp[i]]) {
					walk = 0;
				}
				if (a[i] == x1 && walk) {
					apply(x1 - 1, 1);
				} else {
					apply(x1, walk);
				}
			} else {
				// no extra for walk unless replace one cycle with walk
				int nct = ct + x2 * w;
				// nct + j - i <= 2 * j
				// nct - i <= j
				int j = nct - i;
				auto ptr = lower_bound(ALL(pos), j);
				bool walk = 0;
				if (ptr == pos.end() || grp[*ptr] != grp[i] || done[*ptr]) {
					walk = 1;
				}
				if (donewalk[grp[i]]) {
					walk = 0;
				}
				apply(x2 - walk, walk);
			}
		} else { // right cycle
			auto apply = [&] (int x) {
				if (x == 0) {
					return;
				}
				delta = 1;
				cerr << "APPLY: " << x << '\n';
				ans += x;
				fincre(i, n - 1, x * w);
				incre(i, n - 1, -x * w);
				incre2(i, n - 1, -x * w);
				// ct + x * w + upd <= 2 * i
				assert(ct + x * w <= 2 * i);
				upd(i, 2 * i - (ct + x * w));
			};
			auto ptr = lower_bound(ALL(pos), i);
			bool walk = 0;
			if (ptr == pos.begin() || grp[*prev(ptr)] != grp[i] || 
					done[*prev(ptr)] || fqsm(*prev(ptr)) > 2 * (*prev(ptr))) {
				walk = 1;
			}
			if (donewalk[grp[i]]) {
				walk = 0;
			}
			if (walk) {
				cerr << "WALK\n";
				donewalk[grp[i]] = 1;
				a[i]--;
				ans++;
				// ct + upd <= 2 * i
				upd(i, 2 * i - ct);
			} else if (!donewalk[grp[i]]) {
				assert(lstgrp[grp[i]] == i);
				upd2(i, INF);
				lstgrp[grp[i]] = *prev(ptr);
				int ct = fqsm(*prev(ptr));
				upd2(*prev(ptr), 2 * (*prev(ptr)) - ct);
			}
			// ct + x * w <= 2 * i
			// x <= (2 * i - ct) / w
			int x2 = (2 * i - ct) / w;
			apply(min({a[i], x1, x2}));
		}
		while (st2[1].FI < 0) {
			int u = st2[1].SE, g = grp[u], v = prvgrp[g];
			upd2(u, INF);
			if (donewalk[g]) {
				continue;
			}
			cerr << "HI " << u << ' ' << g << ' ' << v << '\n';
			if (v == -1) {
				continue;
			}
			donewalk[g] = 1;
			int w = 2 * min(v - lft[v], rht[v] - v);
			if (v - lft[v] <= rht[v] - v) {
				fincre(v + 1, n - 1, -w);
				incre(v + 1, n - 1, w);
				incre2(v + 1, n - 1, w);
			} else {
				fincre(v, n - 1, -w);
				incre(v, n - 1, w);
				incre2(v, n - 1, w);
			}
		}
		if (delta) {
			prvgrp[grp[i]] = i;
		}
	}
	cout << tot - ans << '\n';
	return 0;
}

Compilation message (stderr)

tortoise.cpp: In function 'void propo(int, int, int)':
tortoise.cpp:64:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   64 | #define MLR int mid = lo + hi >> 1, lc = u << 1, rc = u << 1 ^ 1
      |                       ~~~^~~~
tortoise.cpp:70:2: note: in expansion of macro 'MLR'
   70 |  MLR;
      |  ^~~
tortoise.cpp:64:17: warning: unused variable 'mid' [-Wunused-variable]
   64 | #define MLR int mid = lo + hi >> 1, lc = u << 1, rc = u << 1 ^ 1
      |                 ^~~
tortoise.cpp:70:2: note: in expansion of macro 'MLR'
   70 |  MLR;
      |  ^~~
tortoise.cpp: In function 'void upd(int, int, int, int, int)':
tortoise.cpp:64:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   64 | #define MLR int mid = lo + hi >> 1, lc = u << 1, rc = u << 1 ^ 1
      |                       ~~~^~~~
tortoise.cpp:82:2: note: in expansion of macro 'MLR'
   82 |  MLR;
      |  ^~~
tortoise.cpp: In function 'void incre(int, int, int, int, int, int)':
tortoise.cpp:64:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   64 | #define MLR int mid = lo + hi >> 1, lc = u << 1, rc = u << 1 ^ 1
      |                       ~~~^~~~
tortoise.cpp:100:2: note: in expansion of macro 'MLR'
  100 |  MLR;
      |  ^~~
tortoise.cpp: In function 'int qmn(int, int, int, int, int)':
tortoise.cpp:64:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   64 | #define MLR int mid = lo + hi >> 1, lc = u << 1, rc = u << 1 ^ 1
      |                       ~~~^~~~
tortoise.cpp:117:2: note: in expansion of macro 'MLR'
  117 |  MLR;
      |  ^~~
tortoise.cpp: In function 'void propo2(int, int, int)':
tortoise.cpp:64:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   64 | #define MLR int mid = lo + hi >> 1, lc = u << 1, rc = u << 1 ^ 1
      |                       ~~~^~~~
tortoise.cpp:135:2: note: in expansion of macro 'MLR'
  135 |  MLR;
      |  ^~~
tortoise.cpp:64:17: warning: unused variable 'mid' [-Wunused-variable]
   64 | #define MLR int mid = lo + hi >> 1, lc = u << 1, rc = u << 1 ^ 1
      |                 ^~~
tortoise.cpp:135:2: note: in expansion of macro 'MLR'
  135 |  MLR;
      |  ^~~
tortoise.cpp: In function 'void upd2(int, int, int, int, int)':
tortoise.cpp:64:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   64 | #define MLR int mid = lo + hi >> 1, lc = u << 1, rc = u << 1 ^ 1
      |                       ~~~^~~~
tortoise.cpp:147:2: note: in expansion of macro 'MLR'
  147 |  MLR;
      |  ^~~
tortoise.cpp: In function 'void incre2(int, int, int, int, int, int)':
tortoise.cpp:64:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   64 | #define MLR int mid = lo + hi >> 1, lc = u << 1, rc = u << 1 ^ 1
      |                       ~~~^~~~
tortoise.cpp:165:2: note: in expansion of macro 'MLR'
  165 |  MLR;
      |  ^~~
tortoise.cpp: In function 'ii qmn2(int, int, int, int, int)':
tortoise.cpp:64:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   64 | #define MLR int mid = lo + hi >> 1, lc = u << 1, rc = u << 1 ^ 1
      |                       ~~~^~~~
tortoise.cpp:182:2: note: in expansion of macro 'MLR'
  182 |  MLR;
      |  ^~~
#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...