Codeforces 1065C Make It Equal

难受的很......比赛时候写出来正解高兴得不得了结果少了特判被hack+fst了.......难受

题意:

给定N个由高度相同的方块摞起来的塔,一次操作能将高度在某个值以上的方块全部消除,代价为消去的方块数量。

规定每次操作代价不能超过给定的K,求至少经过多少次操作才能将所有塔的高度变得相同。

题解:

首先把所有塔的高度减去其中的最小值,问题就变成了将塔消完所需要的步数。

然后维护一个前缀和数组 $ b $ , $ b[i] $ 表示有多少塔的高度(削过之后)大于 $ i $ 。

或者可以理解为:在高度为 $ i $ 处有多少方块。

这样我们就得到了一个一维数组b。

由于每次操作都会消去一层或多层内所有方块,所以可以将数组b理解为「一层一层消,每次所需要的代价」。

接下来所要做的就是合并这些代价,使合并后每段的和都不超过给定的k。

合并后有几段,就是需要操作多少次。

注意特判

· 如果只有一个塔,那么直接输出0.

· 如果所有塔高度相同,那么直接输出0.


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
LL n,k;
int a[200050];
bool cmp(int x,int y){
    return x>y;
}
int minn=2147483647,maxn=0;
int b[200050];
int main(){
    scanf("%lld%lld",&n,&k);
    for(int i(1);i<=n;i++)scanf("%d",&a[i]),minn=min(minn,a[i]),maxn=max(maxn,a[i]);
    if(n==1){
        cout<<0;
        return 0;
    }
    for(int i(1);i<=n;i++){
        a[i]-=minn;
        b[1]++;
        b[a[i]+1]--;
    }
    for(int i(2);i<=n;i++){
        if(a[i]!=a[1])break;
        if(i==n){
            cout<<0;
            return 0;
        }
    }
    for(int i(2);i<=maxn;i++)b[i]+=b[i-1];
    int tmp=0,ans=1;
    for(int i(1);i<=maxn;i++){
        if(tmp+b[i]<=k)tmp+=b[i];
        else ans++,tmp=b[i];
    }
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/soul-M/p/9776086.html