WYT的刷子

WYT的刷子

题目描述

WYT有一把巨大的刷子,刷子的宽度为M米,现在WYT要使用这把大刷子去粉刷有N列的栅栏(每列宽度都为1米;每列的高度单位也为米,由输入数据给出)。

使用刷子的规则是:

  1. 与地面垂直,从栅栏的底部向上刷
  2. 每次刷的宽度为M米(当剩余栅栏宽度不够M米的话,刷子也可以使用,具体看样例2)
  3. 对于连续的M列栅栏,刷子从底向上,刷到的高度只能到这M列栅栏的最低高度。

WYT请你回答两个问题:

  1. 最少有多少个单位面积不能刷到(单位面积为1平米)
  2. 在满足第一问的条件下,最少刷几次?

输入格式

共两行:

第一行两个整数N和M。

第二行共N个整数,表示N列栅栏的高度

输出格式

一行,两个整数,分别为最少剩余的单位面积数量和最少刷的次数。

样例

样例输入1

5 3
5 3 4 4 5

样例输出1

3
2

样例输入2

10 3
3 3 3 3 3 3 3 3 3 3

样例输出2

0
4

样例输入3

7 4
1 2 3 4 3 2 1

样例输出3

4
4

样例1的解释:

image

高度分别为 5 3 4 4 5 如上:

黄色的方块表示共有3个单位面积没刷上

绿色的框和红色的框表示一共刷了两次。

数据范围与提示

30%的数据:N<=10^3

50%的数据:N<=10^5

100%的数据:1<=N<=10^6, 1<=M<=10^6,N>=M, 每列栅栏的高度<=10^6.

code

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 10, INF = 0x3f3f3f3f;

struct Node {
    int id;
    long long high;
} sol[maxn], solmin[maxn], solmax[maxn];

long long height[maxn], f[maxn];
long long ans = 0;
int flag = 1, t = 0;
int n, m;
void get_min() {
    for (int i = 1; i <= n; i++) {
        while (flag <= t && sol[t].high >= height[i]) t--;
        t++;
        sol[t].id = i;
        sol[t].high = height[i];
        if (i >= m) {
            if (sol[flag].id <= i - m)
                flag++;
            solmin[i].high = sol[flag].high;
            solmin[i].id = sol[flag].id;
        }
    }
    for (int i = 1; i < m; i++) {
        solmin[i].id = i;
        solmin[i].high = -INF;
    }
}

void get_max() {
    flag = 1, t = 0;
    for (int i = 1; i <= n; i++) {
        while (flag <= t && solmax[t].high <= solmin[i].high) t--;
        solmax[++t].id = i;
        solmax[t].high = solmin[i].high;
        if (i >= m) {
            if (solmax[flag].id <= i - m)
                flag++;
            f[i - m + 1] = solmax[flag].high;
            ans += height[i - m + 1] - f[i - m + 1];
        }
    }
    long long maxh = -INF;
    for (int i = n; i > n - m + 1; i--) {
        maxh = max(maxh, solmin[i].high);
        f[i] = maxh;
        ans = ans + height[i] - f[i];
    }
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> height[i];
    get_min();
    get_max();
    int last = 1, num = 1;
    for (int i = 1; i <= n; i++) {
        if (i - last + 1 > m || f[last] != f[i]) {
            last = i;
            num++;
        }
    }
    cout << ans << endl << num << endl;
    return 0;
}
posted @ 2020-07-03 11:43  hyskr  阅读(214)  评论(0编辑  收藏  举报