CodeForces Round#523(div2)B-Views Matter (模拟水题)

原题链接
http://codeforces.com/contest/1061/problem/B
B. Views Matter
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You came to the exhibition and one exhibit has drawn your attention. It consists of n stacks of blocks, where the i-th stack consists of ai blocks resting on the surface.

The height of the exhibit is equal to m. Consequently, the number of blocks in each stack is less than or equal to m.

There is a camera on the ceiling that sees the top view of the blocks and a camera on the right wall that sees the side view of the blocks.
在这里插入图片描述
Find the maximum number of blocks you can remove such that the views for both the cameras would not change.

Note, that while originally all blocks are stacked on the floor, it is not required for them to stay connected to the floor after some blocks are removed. There is no gravity in the whole exhibition, so no block would fall down, even if the block underneath is removed. It is not allowed to move blocks by hand either.

Input
The first line contains two integers n and m (1≤n≤100000, 1≤m≤109) — the number of stacks and the height of the exhibit.

The second line contains n integers a1,a2,…,an (1≤ai≤m) — the number of blocks in each stack from left to right.

Output
Print exactly one integer — the maximum number of blocks that can be removed.

Examples
input
5 6
3 3 3 3 3
output
10
input
3 5
1 2 4
output
3
input
5 5
2 3 1 4 4
output
9
input
1 1000
548
output
0
input
3 3
3 1 1
output
1
Note
The following pictures illustrate the first example and its possible solution.

Blue cells indicate removed blocks. There are 10 blue cells, so the answer is 10.
在这里插入图片描述
题意:
有n列木块摆在地上,第i列有ai个木块摞在一起,现在根据原来摆的样子得到俯视图以及右视图。问最多可以从这些木块种拿走多少块,还能保证俯视图和右视图不变。(木块可以悬空,就是说木块下面不一定需要木块支撑,还请仔细看样例说明)
题解:
这道题目,由于每一列之间毫无关系,所以可以先排序之后再来计算,从小到大排序后,遍历整体,此时定义一个now值,来记录便利过程中此时的高度(因为为了保证右视图一样),再具体分情况讨论。(最终答案数据类型要用long long)
附上AC代码:

/*
过程可能写的比较繁琐,望包含
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,st[100005];
long long sum=0,d=0,f=0;//d用于记录第i列前有被强行“入征”的数量;f用来记录解放被强行“入征”的数量
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
    {
        scanf("%d",st+i);
    }
    sort(st,st+n);//从小到大排序
    st[n]=1000000010;
    int nowh=0;
    int i;
    for(i=0;i<n;i++)
    {
        if(st[i]==0)continue;//如果是0直接跳过
        /*如果当前的高度等于i列的高度,并且第i列起码有两个木块,并且再第i列前有被强行“入征”的
            这样既可以在保证右视图的情况下还有更灵活木块可以去帮助
        */
        if(nowh==st[i]&&st[i]>1&&d>0)
        {
            if(d>0){
                d--;//“入征数量减一”
                f++;//解放数量加一
            }
        }
        if(st[i]==st[i+1])//如果前后相等,则nowh只向上加一,总数要st[i]-1,因为只被入征了一个
        {
            if(nowh<st[i])
                nowh++;
            sum+=st[i]-1;
        }
        else//前面的小于后面的
        {
            if(st[i]>nowh)//如果第i列大于nowh
            {
                 sum+=nowh;//可以扣去nowh个
                 d+=st[i]-nowh-1;//强行“入征”数量增加

            }
            else//第i列等于nowh
                sum+=nowh-1;//还是会征用一个以保证俯视图正确
            nowh=st[i];
        }
    }
    sum+=f;//扣去的加上入征后又被解放的
    printf("%lld",sum);
    return 0;
}

欢迎评论!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值