제출 #750267

#제출 시각아이디문제언어결과실행 시간메모리
750267blue서열 (APIO23_sequence)C++17
100 / 100
1271 ms127472 KiB
#include "sequence.h"
#include <bits/stdc++.h>
using namespace std;

using vi = vector<int>;
using vvi = vector<vi>;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using pii = pair<int, int>;
using vpii = vector<pii>;
using pll = pair<ll, ll>;
using vpll = vector<pll>;

#define sz(x) int(x.size())

const int inf = 10'000'000;

const int mx = 500'000;

int N;

vi A;

vi V;

struct sdata
{
	int sm = 0;

	int prefmin = 0;
	int prefmax = 0;

	int suffmin = 0;
	int suffmax = 0;

	sdata()
	{
		;
	}

	sdata(int V)
	{
		sm = V;

		prefmin = min(V, 0);
		suffmin = min(V, 0);

		prefmax = max(V, 0);
		suffmax = max(V, 0);
	}
};

sdata combine(sdata a, sdata b)
{
	sdata res;

	res.sm = a.sm + b.sm;

	res.prefmin = min(a.prefmin, a.sm + b.prefmin);
	res.prefmax = max(a.prefmax, a.sm + b.prefmax);

	res.suffmin = min(b.suffmin, b.sm + a.suffmin);
	res.suffmax = max(b.suffmax, b.sm + a.suffmax);

	return res;
}

struct segtree
{
	int l;
	int r;

	sdata v;

	segtree* left = NULL;
	segtree* right = NULL;


	segtree()
	{
		;
	}

	segtree(int L, int R)
	{
		l = L;
		r = R;
		if(l == r)
			return;

		int m = (l + r)/2;

		left = new segtree(l, m);
		right = new segtree(m+1, r);
	}

	void update(int I, int V)
	{
		if(l == r)
		{
			v = sdata(V);
		}
		else
		{
			if(I <= (l+r)/2)
				left->update(I, V);
			else
				right->update(I, V);

			v = combine(left->v, right->v);
		}
	}

	sdata query(int L, int R)
	{
		if(R < L)
			return sdata(0);

		if(L <= l && r <= R)
			return v;
		else if(R <= (l+r)/2)
			return left->query(L, R);
		else if(L >= (l+r)/2 + 1)
			return right->query(L, R);
		else
			return combine(left->query(L, R), right->query(L, R));
	}
};



vvi val;

int sequence(int N_, vi A_)
{
	N = N_;
	A = vi{0};

	for(int a : A_)
		A.push_back(a);


	vi lst[1+N];
	for(int i = 1; i <= N; i++)
		lst[A[i]].push_back(i);


	segtree S(1, N);

	for(int i = 1; i <= N; i++)
		S.update(i, +1);


	int res = 0;


	for(int v = 1; v <= N; v++)
	{

		for(int i : lst[v])
			S.update(i, 0);

		for(int i : lst[v-1])
			S.update(i, -1);





		if(lst[v].empty())
			continue;



		// cerr << "\n\n\n";
		// cerr << v << " : ";
		// for(int u : lst[v])
		// 	cerr << u << ' ';
		// cerr << '\n';

		// for(int i = 1; i <= N; i++)
		// 	cerr << S.query(i, i).sm << ' ';
		// cerr << '\n';


		int H;

		vi Z{0};

		for(int i : lst[v])
			Z.push_back(i);

		H = sz(Z) - 1;

		vector<sdata> dv(1 + H);

		dv[0] = S.query(1, Z[1] - 1);

		for(int i = 1; i < H; i++)
		{
			// cerr << i << " query = " << Z[i]+1 << ' ' << Z[i+1] - 1 << '\n';
			dv[i] = S.query(Z[i] + 1, Z[i+1] - 1);
		}

		dv[H] = S.query(Z[H] + 1, N);


		vi totsum(1 + H);
		totsum[0] = 0;

		for(int i = 1; i <= H; i++)
			totsum[i] = totsum[i-1] + dv[i-1].sm;


		/*
[1] l - 1 - totsum[l] + dv[l-1].suffmin <= r - dv[r].prefmin - totsum[r]

[2] l - 1 + totsum[l] - dv[l-1].suffmax <= r + totsum[r] + dv[r].prefmax
		*/


		// cerr << "hello!\n";

		val = vvi(4, vi(1+H));
		for(int i = 1; i <= H; i++)
		{
			val[0][i] = i - 1 - totsum[i] + dv[i-1].suffmin;

			val[1][i] = i - dv[i].prefmin - totsum[i];

			val[2][i] = i - 1 + totsum[i] - dv[i-1].suffmax;

			val[3][i] = i + totsum[i] + dv[i].prefmax;
		}

		vpii lst1;

		vpii lst2;

		// cerr << "A\n";

		for(int i = 1; i <= H; i++)
		{
			lst1.push_back({val[0][i], -i});
			lst1.push_back({val[1][i], +i});

			lst2.push_back({val[2][i], -i});
			lst2.push_back({val[3][i], +i});
		}

		vi updpos(1+H), querpos(1+H);

		sort(lst1.begin(), lst1.end());
		sort(lst2.begin(), lst2.end());

		// cerr << "B\n";

		for(int i = 1; i <= sz(lst1); i++)
		{
			if(lst1[i-1].second < 0)
				updpos[-lst1[i-1].second] = i;
			else
				querpos[lst1[i-1].second] = i;
		}

		vi bit(1+2*H, 1'000'000'000);

		// cerr << "C\n";

		for(pii pp : lst2)
		{
			if(pp.second < 0)
			{
				int i = -pp.second;
				//update

				for(int j = updpos[i]; j <= 2*H; j += j&-j)
					bit[j] = min(bit[j], i);
			}
			else
			{
				int i = pp.second;
				//query

				for(int j = querpos[i]; j >= 1; j -= j&-j)
					res = max(res, i - bit[j] + 1);
			}
		}
		





		// cerr << "current res = " << res << '\n';

	}


	return res;
}
#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...