Expected score: 100 + 30 + 0 = 130
Actual score: 70 + 30 + 0 = 100
summary
Set of test follies:
T1 uses the line segment tree to write the maximum and minimum values of a monotonic sequence.
T1 thinks that \ (mlog^2n \) can run over the data of \ (10 ^ 6 \).
The initial value of T2 \(dp \) is incorrectly assigned. Fortunately, there is a large example = =;
T1 median
Algorithm 1
Direct the median dichotomy, and then use upper_ Just check the bound directly.
Complexity \ (O(mlog^2 n) \)
Expected score: \ (70pts \)
code
#include<bits/stdc++.h> #define int long long using namespace std; const int MAXN = 7e5 + 5; const int INF = 1e9 + 7; int read() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();} return x * f; } int n, m, a[MAXN], Mid, b[MAXN]; int l_1, l_2, r_1, r_2; bool Check(int x) { int ret_1 = upper_bound(a + l_1, a + r_1 + 1, x) - a; int ret_2 = upper_bound(b + l_2, b + r_2 + 1, x) - b; ret_1--, ret_2--; ret_1 = ret_1 - l_1 + 1, ret_2 = ret_2 - l_2 + 1; if(ret_1 + ret_2 >= Mid) return true; return false; } int tmp[MAXN * 2]; signed main(){ n = read(), m = read(); for (int i = 1; i <= n; i++) a[i] = read(); for (int i = 1; i <= n; i++) b[i] = read(); for (int i = 1; i <= m; i++) { int opt = read(); if(opt == 1) { int x = read(), y = read(), z = read(); if(x == 0) a[y] = z; else b[y] = z; } else { l_1 = read(), r_1 = read(), l_2 = read(), r_2 = read(); int l = min(a[l_1], b[l_2]), r = max(a[r_1], b[r_2]), Ans; Mid = (r_1 - l_1 + 1) + (r_2 - l_2 + 1); Mid = Mid / 2 + 1; while(l <= r) { int mid = (l + r) >> 1; if(Check(mid)) Ans = mid, r = mid - 1; else l = mid + 1; } cout<<Ans<<"\n"; } } return 0; }
Algorithm II
Bisect a median \ (x \) in \ (a \), and then find its expected position \ (POS \) in \ (b \). If \ (b {pos - 1} \ Leq x \ Leq b {POS + 1} \), the enumerated number is legal.
Note that the median may appear in both \ (a \) and \ (b \), so you need to do two bisections.
This algorithm needs to judge many situations, so I didn't write it. lazy
Complexity \ (O(mlogn) \)
Expected score: \ (100pts \)
#include <cstdio> #include <cmath> #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 5e5 + 10; int n,m,t; int a[MAXN],b[MAXN]; inline int read(){ int s = 0, f = 0;char ch = getchar(); while (!isdigit(ch)) f |= ch == '-', ch = getchar(); while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar(); return f ? -s : s; } inline int Max(int x,int y) {return x > y ? x : y;} inline int Min(int x,int y) {return x < y ? x : y;} inline int Get_Ans_A(int l,int r,int L,int R) { int Len = r - l + 1 + R - L + 1,id = Len / 2; int LL = l,RR = r; while(LL <= RR) { int mid = (LL + RR) >> 1; int pos = id - (mid - l + 1) + L; if(mid - l == id && a[mid] <= b[L]) return a[mid]; if(pos > R) {LL = mid + 1;continue;} if(pos < L) {RR = mid - 1;continue;} if((b[pos + 1] >= a[mid] || pos == R) && a[mid] >= b[pos]) return a[mid]; if(a[mid] < b[pos]) LL = mid + 1; else RR = mid - 1; } return 0; } inline int Get_Ans_B(int l,int r,int L,int R) { int Len = r - l + 1 + R - L + 1,id = Len / 2; int LL = l,RR = r; while(LL <= RR) { int mid = (LL + RR) >> 1; int pos = id - (mid - l + 1) + L; if(mid - l == id && b[mid] <= a[L]) return b[mid]; if(pos > R) {LL = mid + 1;continue;} if(pos < L) {RR = mid - 1;continue;} if((a[pos + 1] >= b[mid] || pos == R) && b[mid] >= a[pos]) return b[mid]; if(b[mid] < a[pos]) LL = mid + 1; else RR = mid - 1; } return 0; } signed main(){ n = read(),m = read(); for(int i = 1;i <= n;i ++) a[i] = read(); for(int i = 1;i <= n;i ++) b[i] = read(); while(m --) { int op = read(); if(op == 1) { int x = read(),y = read(),z = read(); if(x) b[y] = z; else a[y] = z; } else { int l = read(),r = read(),L = read(),R = read(); int Ans = Get_Ans_A(l,r,L,R); if(!Ans) Ans = Get_Ans_B(L,R,l,r); printf("%d\n",Ans); } } return 0; }
Algorithm III
Recursive solution.
Assuming that the current acquisition is the largest \ (k \) of the interval, halve \ (k \) and put it at the corresponding position of the two sequences, \ (s \) and \ (t \), compare \ (a_s \) and \ (b_t \), and assume \ (a_s < b_t \), then the answer can become the largest number of \ (\ frac {k}{2} \) of the interval \ ([s + 1, r_1], [l_2, r_2] \). (because those numbers in the \ (a \) sequence smaller than \ (a[s] \) can all be rounded off), and then recursion can be used.
Complexity \ (O(mlogn) \)
code
/* Recursive solution */ #include<bits/stdc++.h> using namespace std; const int MAXN = 5e5 + 5; int read() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();} return x * f; } int n, m; int a[MAXN], b[MAXN]; int Kth(int ta[], int sta, int tb[], int stb, int k) { if (sta > stb) return Kth(tb, stb, ta, sta, k); // Make sure the front one is short if (sta == 0) return tb[k]; if (k == 1) return min(ta[1], tb[1]); int ka = min(sta, k / 2), kb = k - ka; if (ta[ka] < tb[kb]) return Kth(ta + ka, sta - ka, tb, stb, k - ka); return Kth(ta, sta, tb + kb, stb - kb, k - kb); } int Query(int la, int ra, int lb, int rb) { int sta = ra - la + 1, stb = rb - lb + 1, siz = sta + stb; return Kth(a + la - 1, sta, b + lb - 1, stb, siz / 2 + 1); } int main(){ n = read(), m = read(); for (int i = 1; i <= n; i++) a[i] = read(); for (int i = 1; i <= n; i++) b[i] = read(); for (int i = 1; i <= m; i++) { int opt = read(); if(opt == 1) { int x = read(), y = read(), z = read(); if(x == 0) a[y] = z; else b[y] = z; } else { int l_1 = read(), r_1 = read(), l_2 = read(), r_2 = read(); printf("%d\n", Query(l_1, r_1, l_2, r_2)); } } return 0; }
T2 min
Algorithm 1:
Analog question meaning, direct \ (dp \)
\(f_i \) represents the maximum value obtained by dividing the first \ (I \) positions.
Transfer equation:
\(dp_{i} = \max_{j = 0}^{j = i - 1}\{dp[j] + f(\min_{x = j + 1}^{i} a_x)\}\)
\(dp_0 = 0\)
Note initialization.
Complexity \ (O(n^2) \)
Expected score: 30pts
memset(dp, -0x3f3f3f3f3f3f, sizeof dp); dp[0] = 0; for (int i = 1; i <= n; i++) { for (int j = 0; j < i; j++) { int x = Query(j + 1, i); dp[i] = max(dp[i], dp[j] + A * x * x * x + B * x * x + C * x + D); } } cout<<dp[n];
Algorithm II
\(A = 0, B = 0, C \leq 0\)
At this time \ (f(x) = Cx + D \)
Set \ (Cy + D = 0 \)
case 1 when \ (z > y \):
\(Cz + D < 0\)
case 2 when \ (W < y \)
\(Cw + D > 0\)
For case 1, we can put it into a group in case 2, so the contribution of \ (case ~1 \) will not be calculated, because \ (W < Z \), if there is no case 2, it will be divided into only one group.
\(\sum f(a_i)(f(a_i) > 0)\)
if(A == 0 && B == 0 && C <= 0) { int Ans = 0; for (int i = 1; i <= n; i++) { if(a[i] * C + D >= 0) Ans += a[i] * C + D; } if(Ans > 0) cout<<Ans; else { int Min = INF; for (int i = 1; i <= n; i++) Min = min(a[i], Min); cout<<Min * C + D; } return 0; }
Algorithm III
Maintain \ (g_x = \ min {x = J} ^ {i}a_x \) with monotone stack. Specifically, the element \ (l_1, l_2 \ dots, l_m \) in the monotone stack represents each \ (l_i \) of \ (g_{l_i} \neq g_{l_i - 1} \) (which is the turning point of the minimum value change)
Point), then \ (\ forall x \in[l_i, l_{i + 1} - 1], g_x \) is the same. At this time, the point with the largest value of \ (dp \) must be the best. Therefore, maintain \ (h_i = \max_{x = l_i}^{l_i + 1}{dp[x]} \), indicating the optimal answer of the corresponding interval of each element taking the minimum value.
In this way, each time the answer is \ (\ max\{h_i + f(g_{l_i}) \} \), using a segment tree
Or you can delete the heap maintenance stack.
Complexity \ (O(nlogn) \)
#include<bits/stdc++.h> #define ll long long using namespace std; const int MAXN = 524287; const long long inf = 0x3f3f3f3f3f3f3f3f; int read() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();} return x * f; } int a[MAXN], st[MAXN], tp, n, A, B, C, D; ll T[MAXN << 1], f[MAXN], mx[MAXN]; void Up(int i, ll x) { for (T[i += MAXN] = x; i >>= 1;) T[i] = max(T[i << 1], T[i << 1 | 1]); } ll Cal(ll x) {return ((A * x + B) * x + C) * x + D; } int main(){ n = read(), A = read(), B = read(), C = read(), D = read(); for (int i = 1; i <= n; i++) a[i] = read(); memset(T, -0x3f, sizeof T); f[0] = 0, mx[1] = 0, st[tp = 1] = a[1]; Up(1, Cal(a[1])); for (int i = 1; i <= n; i++) { f[i] = T[1]; ll x = f[i]; while(st[tp] > a[i + 1] && tp) x = max(x, mx[tp]), Up(tp--, -inf); st[++tp] = a[i + 1], mx[tp] = x, Up(tp, x + Cal(st[tp])); } cout<<f[n]; return 0; }
T3
std
#include<cstdio> #include<algorithm> #define ls p << 1 #define rs p << 1 | 1 #define rt 1, 1, Q const int N = 1e5 + 10, Y = 2e5 + 10, P = 1e9 + 7; int ri() { char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1; for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f; } int t[N << 2], tm[N << 2], c[Y], b[Y], l[Y], r[Y], pr[Y], to[Y << 1], nx[Y << 1], Q, n, m, k, H; void add(int x, int p) {to[++H] = 1LL * to[pr[x]] * (1 - p) % P; nx[H] = pr[x]; pr[x] = H;} struct D {int l, r;} q[N]; struct X {int x, y, p;}p[Y]; bool cmp1(X a, X b) {return a.y < b.y;} bool cmp2(D a, D b) {return a.l == b.l ? a.r < b.r : a.l < b.l;} int Pow(int x, int k) { int r = 1; for(;k;x = 1LL * x * x % P, k >>= 1) if(k & 1) r = 1LL * r * x % P; return r; } void B(int p, int L, int R) { tm[p] = 1; if(L == R) return void(t[p] = 1); int m = L + R >> 1; B(ls, L, m); B(rs, m + 1, R); t[p] = t[ls] + t[rs]; } void Tag(int p, int v) {tm[p] = 1LL * tm[p] * v % P; t[p] = 1LL * t[p] * v % P;} void Pd(int p) {if(tm[p] != 1) Tag(ls, tm[p]), Tag(rs, tm[p]), tm[p] = 1;} void M(int p, int L, int R, int st, int ed, int v) { if(L == st && ed == R) return Tag(p, v); int m = L + R >> 1; Pd(p); if(st <= m) M(ls, L, m, st, std::min(ed, m), v); if(ed > m) M(rs, m + 1, R, std::max(st, m + 1), ed, v); t[p] = (t[ls] + t[rs]) % P; } void C(int x) { if(l[x] > r[x]) return ; int m = Pow(1 - (to[pr[x]] - b[x]) % P, P - 2); pr[x] = nx[pr[x]]; M(rt, l[x], r[x], 1LL * (1 - (to[pr[x]] - b[x]) % P) * m % P); } int main() { //freopen("max.in","r",stdin); //freopen("max.out","w",stdout); n = ri(); m = ri(); Q = ri(); int tp = 0; for(int i = 1;i <= m; ++i) { int x = ri(), y = ri(), px = ri(); if(!px || !y) continue; p[++tp].x = x; p[tp].y = y; p[tp].p = px; } std::sort(p + 1, p + tp + 1, cmp1); for(int i = 1;i <= n; ++i) to[++H] = 1, pr[i] = H; for(int i = 1;i <= tp; ++i) add(p[i].x, p[i].p); for(int i = 1;i <= n; ++i) b[i] = to[pr[i]]; for(int i = 1;i <= Q; ++i) q[i].l = ri(), q[i].r = ri(); std::sort(q + 1, q + Q + 1, cmp2); int L = 1, R = 0; for(int i = 1;i <= n; ++i) { for(;L <= R && q[L].r < i; ++L) ; for(;q[R + 1].l <= i && R < Q; ++R) ; l[i] = L; r[i] = R; } B(rt); int A = 0; p[0].y = 0; for(int i = tp, j; i; i = j) { for(j = i;p[j].y == p[i].y && j; --j) C(p[j].x); A = (A + 1LL * t[1] * (p[i].y - p[j].y)) % P; } A = (1LL * p[tp].y * Q - A) % P; printf("%d\n", (A + P) % P); return 0; }