CF1891C Smilo and Monsters

题目链接

题目大意

给出一个长度为 $n(1 \leq n \leq 2*10^5)$ 的数组 $a_i(1 \leq a_i \leq 10^9)$ ,你可以进行以下两个操作

  • 将其中任意一个数的值减少 $1$ ,并使你的计数器 $cnt++$ ,

  • 将其中任意一个数的值减少 $cnt$ ,并使你的计数器 $cnt$ 归零

求使一个数组所有元素归零的最小操作数

思路

不难发现,我们可以先把数组中较小的数用第一个操作归零,然后把数组中较大的数用第二个操作归零,这样做最大化利用 $cnt$ ,可以确保操作数是最小的

所以先将数组从小到大排序一下,用双指针 $l,r$ 分别指向数组的头和尾,再按照贪心思路进行模拟即可

代码

#include<bits/stdc++.h>
#define int long long
#define in inline
#define ri register
#define _123hh2 0
using namespace std;
in int read()
{
    int x=0,f=1;char ch=getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}return x*f;
}
in void write(int x) {if(x<0) {x=-x;putchar('-');}if(x>9) write(x/10);putchar(x%10+'0');}
const int maxn=2e5+1;
int awa[maxn];
signed main()
{
    int t=read();
    while(t-->0)
    {
        int n=read();
        for(int i=1;i<=n;i++) awa[i]=read();
        sort(awa+1,awa+1+n);
        int l=1,r=n,cnt=0,ans=0;
        while(l<=r)
        {
            if(l==r)
            {
                if(!awa[l]) break;
                if(!cnt) {ans+=awa[l]==1?1:(awa[l]+3)/2;break;}
                else {ans+=(awa[l]-cnt+3)/2;break;}
            }
            if(cnt+awa[l]>=awa[r])
            {
                awa[l]-=awa[r]-cnt;
                ans+=awa[r]-cnt+1,cnt=0,r--;
                if(!awa[l]) l++;
            }
            else cnt+=awa[l],ans+=awa[l],l++;
        }
        write(ans),puts("");
    }
    return _123hh2;
}
更新于

请我喝[茶]~( ̄▽ ̄)~*

123hh2 微信支付

微信支付

123hh2 支付宝

支付宝

123hh2 贝宝

贝宝