Problem solving - "MLOI" Rabbit

Posted by BRUUUCE on Fri, 28 Jan 2022 00:55:51 +0100

Rabbit Ji

\(\texttt{Link}\)

Simple topic meaning

There are \ (n \) small stakes in a row. The height of the \ (I \) small stake is \ (h_i \) and the score is \ (c_i \).

If a rabbit is on the \ (I \) stake, she will get \ (c_i \); At the same time, if \ (|i - j| \ NEQ 1) \ wedge (h_j < h_i) \ wedge (\ forall \ min \ {I, J \} < K < \ Max \ {I, J \}, h_k < h_i) \), she can jump from the \ (I \) stake to the \ (J \) stake; Of course, she can also stop jumping.

Mark \ (f_i \) indicates the maximum value of the total score obtained by the rabbit from jumping from the (I \) small stake.

Please find \ (\ sum \ limits {I = 1} ^ {n} f_i \) and \ (\ mathrm {XOR} {I = 1} ^ {n} | f_i \).

Data range

For data of \ (100 \% \): meet \ (1 \leq n \leq {3 \times 10^6} \), \ (\ forall 1 \leq i \leq n, \ 1 \leq h_i \leq {10}^{18} \wedge |c_i| \leq {10}^{10} \).

\(\texttt{Solution}\)

Since the little rabbit can only jump to the lower place, it is considered to build a Cartesian tree to meet the nature of large root pile, i.e. \ (h_{f_} \ GEQ h_ \).

  • \(\ texttt{lson[u]} \) represents the left son of \ (U \).
  • \(\ texttt{rson[u]} \) represents the right son of \ (U \).

\(\texttt{code}\):

void build(int u)
{
	while (top && h[u] > h[S[top]]) lson[u] = S[top--];
	rson[S[top]] = u; S[++top] = u;
}

Where \ (\ texttt {h [u] > H [s [top]]} \) can make the equal condition of \ (H {f} = h}) as \ (\ texttt{rson[f[u]] = u} \); Of course, if it is also written as \ (\ texttt{h [u] > = h [s [top]]} \), then the wait condition is \ (\ texttt{lson[f[u]] = u} \).

Consider \ (\ texttt{dp} \):

  • Definition \ (l_ \) represents the left end point of the interval corresponding to the subtree with \ (u \) as the root.
  • Definition \ (r_ \) represents the right end of the interval corresponding to the subtree with \ (u \) as the root.
  • Definition \ (f_ \) represents the maximum value of the total score obtained by the rabbit from jumping from the (u \) small stake.
  • Definition \ (g_ \) means \ (\ Max \ {f_i \ | \ l_ < I < r_ \} \), which is strictly less than, that is, it does not contain two endpoints.

Consider the state transition of a node \ (u \):

  • \(g_ \) and initial value is \ (0 \), \ (f_ \) initial value is \ (c_ \).

  • Consider the left son:

    • \(g_u = \max\{ g_u, g_{\texttt{lson[u]}} \}\)
    • \(g_u = \max\{ g_u, g_{u - 1}\}, {u - 1} > L_u\)
    • \(f_u = \max\{ f_u, c_u + g_{\texttt{lson[u]}} \}, {u - 1} > L_u\)
    • \(f_u = \max\{ f_u, c_u + f_{L_u} \}, {u - 1} > L_u\)
  • Consider the right son:

    • \(g_u = \max\{ g_u, g_{\texttt{rson[u]}} \}\)

    • \(g_u = \max\{ g_u, g_{u + 1} \}, {u + 1} > R_u\)

    • Conditions \ ({h {\ texttt {rson [u]}} = u} \ wedge {\ texttt {rson [u]} > {U + 1} \):

      • \(f_u = \max\{ f_u, c_u + g_{\texttt{lson[rson[u]]}} \}\)
      • \(f_u = \max\{ f_u, c_u + f_{\texttt{rson[u]} - 1}\}, {\texttt{rson[u]} - 1} > {u + 1}\)
    • Conditions \ ({h {\ texttt {rson [u]}} \ NEQ u} \ wedge {{U + 1} < R _} \)

      • \(f_u = \max\{ f_u, c_u + g_{\texttt{rson[u]}} \}\)
      • \(f_u = \max\{ f_u, c_u + g_{R_u} \}\)
    • Condition \ ({{U + 1} < r_} \)

  • Consider \ (u \) yourself:

    • \(g_u = \max\{ g_u, f_u \}, L_u < u < R_u\)

The above judgment related to \ (l_ \) and \ (r_ \) is whether the nodes adjacent to \ (\ texttt{check} \) and \ (u \) can contribute to \ (g_ \) or \ (f_ \).

Because the code for building Cartesian tree is \ (\ texttt {h [u] > H [s [top]]} \), only \ (H {\ texttt {rson [u]} = h _} \) may appear, and \ (H {\ texttt {lson [u]} = h _} \) will not appear.

matters needing attention:

  • \(f_ \) is in the range of \ (\ texttt{long long} \), while \ (\ sum \ limits {u = 1} ^ {n} f_ \) may be out of range.
  • Because the range of \ (\ sum \ limits {u = 1} ^ {n} f _ \) will not exceed much, it is enough to press \ (\ texttt{mod} = {10}^{18} \) to the \ (2 \) bit.
  • Remember to supplement \ (0 \) when pressing the position, and do not appear leading \ (0 \).
  • Use the input method given in the title. If not, it may be \ (\ texttt{TLE} \).

\(\texttt{code}\)

  • \(\ texttt{dp[u]} \) means \ (f_ \).
  • \(\ texttt{dpp[u]} \) means \ (g_ \).
#include <cstdio>
#include <cassert>

#define int long long
#define uint unsigned int

namespace Read
{
	static const int buf_size = 1 << 12;
	
	static unsigned char buf[buf_size];
	static int buf_len = 0, buf_pos = 0;
	
	inline bool isEOF()
	{
		if (buf_pos == buf_len)
		{
			buf_pos = 0; buf_len = fread(buf, 1, buf_size, stdin);
			if (buf_pos == buf_len) return true;
		}
		return false;
	}
	
	inline char readChar()
	{
		return isEOF() ? EOF : buf[buf_pos++];
	}
	
	inline int rint()
	{
		int x = 0, fx = 1; char c = readChar();
		while (c < '0' || c > '9') { fx ^= (c == '-'); c = readChar(); }
		while ('0' <= c && c <= '9') { x = (x << 3) + (x << 1) + (c ^ 48); c = readChar(); }
		if (!fx) return -x;
		return x;
	}
	
	inline void read(int &x)
	{
		x = rint();
	}
	
	template<typename... Ts>
	inline void read(int &x, Ts &...rest)
	{
		x = rint();
		read(rest...);
	}
} using namespace Read;

namespace Write
{
	static const int buf_size = 1 << 12;
	static char buf[buf_size];
	static int buf_pos = 0;
	
	inline void flush()
	{
		if (buf_pos)
		{
			fwrite(buf, 1, buf_pos, stdout);
			buf_pos = 0; fflush(stdout);
		}
	}
	
	inline void writeChar(char x)
	{
		if (buf_pos == buf_size)
		{
			fwrite(buf, 1, buf_size, stdout);
			buf_pos = 0;
		}
		buf[buf_pos++] = x;
	}
	
	inline void write(int x, char end = 0)
	{
		if (x < 0) { writeChar('-'); x = -x; }
		char str[24]; int n = 0;
		do { str[n++] = ((x % 10) ^ 48); x /= 10; } while (x);
		while (n--) writeChar(str[n]);
		if (end) writeChar(end);
		flush();
	}
} using namespace Write;

namespace Math
{
	int Max(int u, int v) { return (u > v) ? u : v; }
	int Min(int u, int v) { return (u < v) ? u : v; }
} using namespace Math;

const int inf = 1e18;
const int mod = 1e18;

const int MAX_n = 3e6;

int n, top;
int h[MAX_n + 5];
int c[MAX_n + 5];

int S[MAX_n + 5];
int L[MAX_n + 5];
int R[MAX_n + 5];
int lson[MAX_n + 5];
int rson[MAX_n + 5];

int dp[MAX_n + 5];
int dpp[MAX_n + 5];

bool vis[MAX_n + 5];

void build(int u)
{
	while (top && h[u] > h[S[top]]) lson[u] = S[top--];
	rson[S[top]] = u; S[++top] = u;
}

void tree_dp(int u)
{
	L[u] = R[u] = u;
	
	if (lson[u])
	{
		tree_dp(lson[u]);
		L[u] = L[lson[u]];
		if (u - 1 > L[u])
		{
			dp[u] = Max(dp[u], dpp[lson[u]]);
			dp[u] = Max(dp[u], dp[L[u]]);
			dpp[u] = Max(dpp[u], dp[u - 1]);
		}
		dpp[u] = Max(dpp[u], dpp[lson[u]]);
	}
	
	if (rson[u])
	{
		tree_dp(rson[u]);
		R[u] = R[rson[u]];
		if (h[rson[u]] == h[u])
		{
			int v = rson[u];
			if (v > u + 1)
			{
				dp[u] = Max(dp[u], dpp[lson[v]]);
				if (v - 1 > u + 1) dp[u] = Max(dp[u], dp[v - 1]); 
			}
		}
		else if (u + 1 < R[u]);
		{
			dp[u] = Max(dp[u], dpp[rson[u]]);
			dp[u] = Max(dp[u], dp[R[u]]);
		}
		dpp[u] = Max(dpp[u], dpp[rson[u]]);
		if (u + 1 < R[u]) dpp[u] = Max(dpp[u], dp[u + 1]);
	}
	dp[u] += c[u];
	if (L[u] < u && u < R[u])
		dpp[u] = Max(dpp[u], dp[u]);
}

signed main()
{
	freopen("jump.in", "r", stdin);
	freopen("jump.out", "w", stdout);
	
	n = rint();
	
	assert(1 <= n && n <= MAX_n);
	
	for (int i = 1; i <= n; build(i++))
	{
		read(h[i], c[i]);
		assert(1 <= h[i] && h[i] <= 1e18);
		assert(-1e10 <= c[i] && c[i] <= 1e10);
	}
	
	tree_dp(rson[0]);
	
	int res_first = 0, res_second = 0, res_xor = 0;
	for (int i = 1; i <= n; i++)
	{
		int now = dp[i];
		res_first += (res_second + now) / mod;
		res_second = (res_second + now) % mod;
		res_xor ^= ((now > 0) ? now : -now);
	}
	if (!res_first) printf("%lld %lld\n", res_second, res_xor);
	else printf("%lld%018lld %lld\n", res_first, res_second, res_xor);
	
	return 0;
}