Live2D

20181030NOIP模拟赛T2

WYT的刷子

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

使用刷子的规则是:

1.与地面垂直,从栅栏的底部向上刷

2.每次刷的宽度为M米(当剩余栅栏宽度不够M米的话,刷子也可以使用,具体看样例2)

3.对于连续的M列栅栏,刷子从底向上,刷到的高度只能到这M列栅栏的最低高度。

WYT请你回答两个问题:

1、最少有多少个单位面积不能刷到(单位面积为1平米)

2、在满足第一问的条件下,最少刷几次?

输入

共两行:

第一行两个整数N和M。

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

输出

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

Input1:

5 3

5 3 4 4 5

Output1:

3

2

Input2:

10 3

3 3 3 3 3 3 3 3 3 3

Output2:

0

4

Input3:

7 4

1 2 3 4 3

Output3:

4

4

样例1的解释:

 

高度分别为       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.

思路:

单调栈裸题

利用和求最大子矩形一样的方法,我们可以用单调栈求出每个高度它对应的区间

如果这个区间小于m,则显然刷不到这个点的最高处

然后我们O(N)的扫三遍

第一遍判出哪些地方一定到不了最高点

第二遍和第三遍求出这些到达不了最高点的地方能达到多高

然后再O(n)扫一遍

就能得到有多少个涂不了色的了

至于涂得次数,贪心就好了

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rii register int i
#define rij register int j
using namespace std;
int n,m,zl[1000005],r[1000005],l[1000005];
long long sum;
int sta[1000005],top,sj[1000005],bj[1000005];
inline int rd(){
    register int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return f?x:-x;
}
int main()
{
    freopen("wyt.in","r",stdin);
    freopen("wyt.out","w",stdout);
    n=rd(),m=rd();
    for(rii=1;i<=n;i++)
    {
        zl[i]=rd();
        sum+=zl[i];
    }
    for(rii=1;i<=n;i++)
    {
        if(top==0)
        {
            top++;
            sta[top]=i;
            continue;
        }
        while(zl[sta[top]]>zl[i])
        {
            r[sta[top]]=i-1;
            top--;
        }
        top++;
        sta[top]=i;
    }
    while(top!=0)
    {
        r[sta[top]]=n;
        top--;
    }
    for(rii=n;i>=1;i--)
    {
        if(top==0)
        {
            top++;
            sta[top]=i;
            continue;
        }
        while(zl[sta[top]]>zl[i])
        {
            l[sta[top]]=i+1;
            top--;
        }
        top++;
        sta[top]=i;
    }
    while(top!=0)
    {
        l[sta[top]]=1;
        top--;
    }
    for(rii=1;i<=n;i++)
    {
        if(r[i]-l[i]+1<m)
        {
            bj[i]=1;
        }
    }
    for(rii=1;i<=n;i++)
    {
        if(bj[i]==1)
        {
            sj[i]=sj[i-1];
        }
        else
        {
            sj[i]=zl[i];
        }
    }
    for(rii=n;i>=1;i--)
    {
        if(bj[i]==1)
        {
            sj[i]=max(sj[i+1],sj[i]);
        }
    }
    for(rii=1;i<=n;i++)
    {
        sum-=sj[i];
    }
    cout<<sum<<endl;
    int ans=0;
    int val=sj[1],l=1;
    for(rii=2;i<=n;i++)
    {
        if(sj[i]!=val)
        {
            int sl=(i-l)/m;
            if(sl*m<(i-l))
            {
                sl++;
            }
            ans+=sl;
            l=i;
            val=sj[i];
        }
    }
    int sl=(n-l+1)/m;
    if(sl*m<(n-l+1))
    {
        sl++;
    }
    ans+=sl;
    cout<<ans;
    return 0;
}

 

posted @ 2018-10-30 16:35  ztz11  阅读(177)  评论(0编辑  收藏  举报