BZOJ 4123 [Baltic2015] Hacker 解题报告
首先,Alice 会选择一个长度为 $\lfloor\frac{n+1}{2}\rfloor$ 的区间,我们把这个长度记为 $len$。
有这么一个结论:令 $F_i$ 为覆盖 $i$ 点的所有长度为 $len$ 的区间的元素和的最小值,那么答案就是 $F_i$ 的最大值。
因为 Bob 可以控制 Alice 最后选择的是什么区间。
【扯淡 ing】大概是这样子:
假设 Alice 一开始选择的是红色的点 $i$,并且蓝色的线以左所覆盖的区间和就是 $F_i$,那么对于 Bob,他就可以选择绿色的点,然后 Alice 逆时针选的话,Bob 就顺时针选 $\dots$ 总之,Bob 的选择只要关于那个对称轴与 Alice 对称就可以了。
所以我们就可以用个单调队列什么的就可以做了。
时间空间复杂度均为 $O(n)$。
1 #include <cstdio> 2 #define N 500000 + 5 3 #define INF 1000000007 4 5 int n, A[N], Sum[N << 1], q[N << 1]; 6 7 inline int getint() 8 { 9 char ch = '\n'; 10 for (; ch != '-' && (ch > '9' || ch < '0'); ch = getchar()) ; 11 int f = ch == '-' ? -1 : 1; 12 int res = ch == '-' ? 0 : ch - '0'; 13 for (ch = getchar(); ch >= '0' && ch <= '9'; ch = getchar()) 14 res = (res << 3) + (res << 1) + ch - '0'; 15 return res * f; 16 } 17 18 int main() 19 { 20 #ifndef ONLINE_JUDGE 21 freopen("4123.in", "r", stdin); 22 freopen("4123.out", "w", stdout); 23 #endif 24 25 n = getint(); 26 for (int i = 1; i <= n; i ++) 27 A[i] = getint(); 28 for (int i = 1; i <= (n << 1); i ++) 29 Sum[i] = Sum[i - 1] + A[i > n ? i - n : i]; 30 int len = n + 1 >> 1, Max = -INF, head = 1, tail = 0; 31 for (int i = len; i < (len << 1); i ++) 32 { 33 for (; head <= tail && Sum[i] - Sum[i - len] <= Sum[q[tail]] - Sum[q[tail] - len]; tail --) ; 34 q[++ tail] = i; 35 } 36 for (int i = (len << 1) - 1; i <= n << 1; i ++) 37 { 38 for (; head <= tail && q[head] + len <= i; head ++) ; 39 for (; head <= tail && Sum[i] - Sum[i - len] <= Sum[q[tail]] - Sum[q[tail] - len]; tail --) ; 40 q[++ tail] = i; 41 int t = Sum[q[head]] - Sum[q[head] - len]; 42 Max = Max > t ? Max : t; 43 } 44 printf("%d\n", Max); 45 46 #ifndef ONLINE_JUDGE 47 fclose(stdin); 48 fclose(stdout); 49 #endif 50 return 0; 51 }