「POI2010」积木 Blocks
Posted ympc2005
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「POI2010」积木 Blocks相关的知识,希望对你有一定的参考价值。
单调栈
可以发现子序列的平均数不小于k就可以使子序列的每个数都不小于k
将每个数减去k,则子序列之和非负即可
记 si = a1 + a2 +....+ ai - k*i
考虑序列的两个端点 l, r
对于 l: l1 < l2 && sl1 <= sl2, 则l1 比 l2 优
对于 r: r1 < r2 && sr1 <= sr2 则r2 比 r1 优
从0到n 将可能最优 l 加入单调栈中,可以发现栈是单调递增的
从n到1 的可能最优 r 的是单调递减的
每次将当前栈中满足sr - sl ≥ 0的 l 都弹出,最后一个被弹出的就是最优的l
而且对与更小的 r,它的值会更大,所以被弹出的l更不会用到
#include <bits/stdc++.h> using namespace std; const int N = 1e6 + 5; typedef long long LL; int n, m, a[N], k, ans, zhan[N], top; LL s[N]; void Solve() { ans = top = 0; zhan[++top] = 0; for (int i = 1; i <= n; i++) { s[i] = s[i - 1] + a[i] - k; if (s[i] < s[zhan[top]]) zhan[++top] = i; } for (int i = n; i; i--) { while (s[i] - s[zhan[top]] >= 0 && top) top--; ans = max(ans, i - zhan[top + 1]); } cout << ans << " "; } int main() { cin >> n >> m; for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int i = 1; i <= m; i++) { scanf("%d", &k); Solve(); } return 0; }
以上是关于「POI2010」积木 Blocks的主要内容,如果未能解决你的问题,请参考以下文章