WYT有一把巨大的刷子,刷子的宽度为M米,如今WYT要使用这把大刷子去粉刷有N列的栅栏(每列宽度都为1米;每列的高度单位也为米,由输入数据给出)。c++
使用刷子的规则是:算法
1.与地面垂直,从栅栏的底部向上刷
2.每次刷的宽度为M米(当剩余栅栏宽度不够M米的话,刷子也可使用,具体看样例2)
3.对于连续的M列栅栏,刷子从底向上,刷到的高度只能到这M列栅栏的最低高度。数组
WYT请你回答两个问题:spa
1.最少有多少个单位面积不能刷到(单位面积为1平米)
2.在知足第一问的条件下,最少刷几回?code
共两行:队列
第一行两个整数N和M。get
第二行共N个整数,表示N列栅栏的高度it
一行,两个整数,分别为最少剩余的单位面积数量和最少刷的次数。class
5 3 5 3 4 4 5
3 2
int tail = -1;//求向右延伸的宽度 for(int i = 1;i <= n+1;++i){//枚举到n+1可使前n个都出列 while(tail >= 0 && a[i] < a[que[tail]]){//维护一个单调不上升的队列 若是第i个的高度比前一个矮了就出队 r[que[tail]] = i - que[tail];//r是当前节点所能向右延伸的距离 --tail; } que[++tail] = i;//把当前位置入队 } tail = -1;//求向左延伸的宽度 for(int i = n;i >= 0;--i){ while(tail >= 0 && a[i] < a[que[tail]]){ l[que[tail]] = que[tail] - i; --tail; } que[++tail] = i; } for(int i = 1;i <= n;++i){ if(l[i] + r[i] - 1 >= m)flag[i] = true;//flag标记能刷完 }
for(int i = 1;i <= n;++i){ if(flag[i])mh[i] = a[i]; else mh[i] = mh[i-1]; } for(int i = n;i > 0;--i){ if(!flag[i])mh[i] = max(mh[i],mh[i+1]); sum -= mh[i]; }
int k = 2,ans = 0;//k=2是由于第一个方块不管如何都要花费一次去刷 while(k <= n){//当前刷到第k个方块了 int cnt = 1;//第一个方块已经花费一次去刷了 while(k < n && mh[k] == mh[k+1]){//若是当前的能刷的最高高度和下一个能刷的最高高度同样 就一块儿刷掉 cnt++;k++; } ans += cnt/m; if(cnt % m)++ans;//保证向上取整 ++k;//进入下个矩形 }
#include<bits/stdc++.h> using namespace std; const int maxn = 1e7+10; typedef long long ll; ll a[maxn],sum,r[maxn],l[maxn],mh[maxn],que[maxn],flag[maxn]; int main(){ int n,m;scanf("%d%d",&n,&m); for(int i = 1;i <= n;++i){scanf("%lld",&a[i]);sum += a[i];} int tail = -1; for(int i = 1;i <= n+1;++i){ while(tail >= 0 && a[i] < a[que[tail]]){ r[que[tail]] = i - que[tail]; --tail; } que[++tail] = i; } tail = -1; for(int i = n;i >= 0;--i){ while(tail >= 0 && a[i] < a[que[tail]]){ l[que[tail]] = que[tail] - i; --tail; } que[++tail] = i; } for(int i = 1;i <= n;++i){ if(l[i] + r[i] - 1 >= m)flag[i] = true; } for(int i = 1;i <= n;++i){ if(flag[i])mh[i] = a[i]; else mh[i] = mh[i-1]; } for(int i = n;i > 0;--i){ if(!flag[i])mh[i] = max(mh[i],mh[i+1]); sum -= mh[i]; } int k = 2,ans = 0; while(k <= n){ int cnt = 1; while(k <= n+1 && mh[k] == mh[k-1]){ cnt++;k++; } ans += cnt/m; if(cnt % m)++ans; ++k; } printf("%lld\n%d",sum,ans); return 0; }