码迷,mamicode.com
首页 > 其他好文 > 详细

「POI2010」积木 Blocks

时间:2020-02-15 11:39:28      阅读:53      评论:0      收藏:0      [点我收藏+]

标签:const   递增   blocks   bottom   code   mes   cin   lock   ase   

单调栈

可以发现子序列的平均数不小于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

标签:const   递增   blocks   bottom   code   mes   cin   lock   ase   

原文地址:https://www.cnblogs.com/ympc2005/p/12310925.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!