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

版权声明:欢迎评论与转载,转载时请注明出处! https://blog.csdn.net/wjl_zyl_1314/article/details/84391803

原题链接
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;
}

欢迎评论!

猜你喜欢

转载自blog.csdn.net/wjl_zyl_1314/article/details/84391803