Submission #985223

#TimeUsernameProblemLanguageResultExecution timeMemory
985223CrazyBotBoySequence (APIO23_sequence)C++17
100 / 100
515 ms51012 KiB
#include "sequence.h"
#include <bits/stdc++.h>
using namespace std;
using lint = long long;
using pi = array<int, 2>;
#define sz(a) ((int)(a).size())
#define all(a) (a).begin(), (a).end()
const int MAXT = 1050000;

struct node {
	int sum, pmin, pmax;
	node() { sum = pmin = pmax = 0; }
	node(int x) {
		sum = x;
		pmin = min(x, 0);
		pmax = max(x, 0);
	}
	node operator+(const node &nd) {
		node ret;
		ret.sum = sum + nd.sum;
		ret.pmin = min(pmin, sum + nd.pmin);
		ret.pmax = max(pmax, sum + nd.pmax);
		return ret;
	}
};

struct bit {
	int tree[MAXT];
	void init() { memset(tree, 0x3f, sizeof(tree)); }
	void add(int x, int v) {
		for (int i = x + 2; i < MAXT; i += i & -i)
			tree[i] = min(tree[i], v);
	}
	int query(int x) {
		int ret = 1e9;
		for (int i = x + 2; i; i -= i & -i)
			ret = min(ret, tree[i]);
		return ret;
	}
	void flush(int x) {
		for (int i = x + 2; i < MAXT; i += i & -i)
			tree[i] = 1e9;
	}
} bit;
struct seg {
	node tree[MAXT];
	int lim;
	void init(int n, int v) {
		for (lim = 1; lim <= n; lim <<= 1)
			;
		for (int i = 0; i < n; i++)
			tree[i + lim] = node(v);
		for (int i = lim - 1; i; i--)
			tree[i] = tree[2 * i] + tree[2 * i + 1];
	}
	void upd(int x, int v) {
		x += lim;
		tree[x] = node(v);
		while (x > 1) {
			x >>= 1;
			tree[x] = tree[2 * x] + tree[2 * x + 1];
		}
	}
	node query(int l, int r) {
		if (l > r)
			return node();
		l += lim;
		r += lim;
		node L, R;
		while (l < r) {
			if (l % 2 == 1)
				L = L + tree[l++];
			if (r % 2 == 0)
				R = tree[r--] + R;
			l >>= 1;
			r >>= 1;
		}
		if (l == r)
			L = L + tree[l];
		return L + R;
	}
} seg;

int sequence(int n, std::vector<int> a) {
	bit.init();
	vector<vector<int>> indices(n);
	for (int i = 0; i < n; i++) {
		a[i]--;
		indices[a[i]].push_back(i);
	}
	seg.init(n, 1);
	int ans = 0;
	for (int i = 0; i < n; i++) {
		if (sz(indices[i]) == 0)
			continue;
		vector<array<int, 3>> PL(sz(indices[i]) + 1), PR(sz(indices[i]) + 1);
		vector<int> vect;
		for (int j = 0; j <= sz(indices[i]); j++) {
			int l = (j ? (indices[i][j - 1]) : -1);
			int r = (j < sz(indices[i]) ? indices[i][j] : n);
			auto lsum = seg.query(0, l).sum;
			auto msum = seg.query(l + 1, r - 1);
			int sx = lsum + msum.pmin;
			int ex = lsum + msum.pmax;
			int sy = 2 * j - ex;
			int ey = 2 * j - sx;
			PL[j] = {sx, sy, j};
			PR[j] = {ex, ey, j};
			vect.push_back(sy);
			vect.push_back(ey);
		}

		sort(all(vect));
		for (auto &[_, y, __] : PL) {
			y = lower_bound(all(vect), y) - vect.begin();
		}
		for (auto &[_, y, __] : PR) {
			y = lower_bound(all(vect), y) - vect.begin();
		}
		sort(all(PL));
		sort(all(PR));
		int j = 0;
		for (int i = 0; i < sz(PR); i++) {
			while (j < sz(PL) && PL[j] <= PR[i]) {
				bit.add(PL[j][1], PL[j][2]);
				j++;
			}
			ans = max(ans, PR[i][2] - bit.query(PR[i][1]));
		}
		for (int k = 0; k < j; k++)
			bit.flush(PL[k][1]);
		for (auto &q : indices[i]) {
			seg.upd(q, -1);
		}
	}
	return ans;
}
#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...