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; }