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[],r[],l[];
long long sum;
int sta[],top,sj[],bj[];
inline int rd(){
register int x=,f=;char ch=getchar();
while(!isdigit(ch)) {f=ch=='-'?:;ch=getchar();}
while(isdigit(ch)) {x=(x<<)+(x<<)+ch-'';ch=getchar();}
return f?x:-x;
}
int main()
{
freopen("wyt.in","r",stdin);
freopen("wyt.out","w",stdout);
n=rd(),m=rd();
for(rii=;i<=n;i++)
{
zl[i]=rd();
sum+=zl[i];
}
for(rii=;i<=n;i++)
{
if(top==)
{
top++;
sta[top]=i;
continue;
}
while(zl[sta[top]]>zl[i])
{
r[sta[top]]=i-;
top--;
}
top++;
sta[top]=i;
}
while(top!=)
{
r[sta[top]]=n;
top--;
}
for(rii=n;i>=;i--)
{
if(top==)
{
top++;
sta[top]=i;
continue;
}
while(zl[sta[top]]>zl[i])
{
l[sta[top]]=i+;
top--;
}
top++;
sta[top]=i;
}
while(top!=)
{
l[sta[top]]=;
top--;
}
for(rii=;i<=n;i++)
{
if(r[i]-l[i]+<m)
{
bj[i]=;
}
}
for(rii=;i<=n;i++)
{
if(bj[i]==)
{
sj[i]=sj[i-];
}
else
{
sj[i]=zl[i];
}
}
for(rii=n;i>=;i--)
{
if(bj[i]==)
{
sj[i]=max(sj[i+],sj[i]);
}
}
for(rii=;i<=n;i++)
{
sum-=sj[i];
}
cout<<sum<<endl;
int ans=;
int val=sj[],l=;
for(rii=;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+)/m;
if(sl*m<(n-l+))
{
sl++;
}
ans+=sl;
cout<<ans;
return ;
}

最新文章

  1. Code First 关系配置整理
  2. 如何发布付费WP8应用
  3. Redis分布式锁服务(八)
  4. appium 处理动态控件
  5. Unity手撸2048小游戏——模块拆分
  6. 如何修改opencms数据库配置
  7. Eclipse开发JavaWeb程序报Server Tomcat v7.0 at localhost was unable to start
  8. hdu 1305 Immediate Decodability
  9. activiti总结
  10. github三大步骤
  11. Java 泛型具体解释
  12. 原生js表单序列化----- FormData
  13. angular指令之complie和link不得不说的故事
  14. JVM GC杂谈之理论入门
  15. Beta第七天
  16. 【转】linux系统中如何进入退出vim编辑器,方法及区别
  17. 面试题:int和Integer的区别
  18. PHP实现微信模板消息发送给指定用户
  19. c++多态及实现原理
  20. CSS3效果:animate实现点点点loading动画效果(一)

热门文章

  1. xml文件读取到数据库
  2. gulpfile配置
  3. Java Struts2 (四)
  4. Javascript 多物体淡入淡出(透明度变化)
  5. mongoDB BI 分析利器 - PostgreSQL FDW (MongoDB Connector for BI)
  6. 万网云解析全面升级开放,支持海外IP解析!
  7. 【Leetcode】【Medium】Search Insert Position
  8. jbd2/dm-2-8 io太高
  9. 第六周 day6 python学习笔记
  10. 面试知识整理-Java基础