AT_arc215_a [ARC215A] Zombie

我去,我怎么黄题都不会做了。

不管了,先挂上洛谷的题目传送门和信友队上的题目传送门吧。

题目描述

有一条长度为 \(L\) 的道路,向左右两侧延伸。在这条路上有 \(N\) 个僵尸,第 \(i\) 个僵尸距离道路左端 \(A_i\) 的位置。这里 \(L\) 和所有 \(A_i\) 都是偶数。

你有 \(K\) 个引诱僵尸的“诱饵”,你可以在道路上的任意位置(包括两端),在任意时刻投放诱饵。但任意时刻,道路上至多只能存在一个诱饵。只要诱饵存在于道路上,所有的僵尸都会以每单位时间 \(1\) 的速度朝向诱饵的位置移动。当一只或多只僵尸和诱饵到达同一位置时,诱饵会被瞬间吃掉并消失。

当道路上没有诱饵时,僵尸不移动。请你求出,当投放诱饵的位置和时机都选择最优时,诱饵在道路上存在的总最长时间。可以证明,答案一定为整数。

你将得到 \(T\) 个测试用例;请分别解答每个用例。

解题思路

为了方便,我们可以先将 \(a\) 数组排序。不难发现无论如何放置诱饵,\(a\) 数组永远都是单调不降的。分析一下操作的性质,最优解可以分成两类:

  • 操作一:在最左边或最右边放上诱饵,贡献为 \(\max(a_1,l-a_n)\)
  • 操作二:在相邻的两只僵尸 \(i,j\) 的中点放上诱饵,贡献为 \(\frac{a_i+a_j}{2}\)

因为做一次操作二会让 \(a_1\) 变大并让 \(a_n\) 变小,所以最优解一定是进行若干次操作二后进行一次操作一。又因为每次做操作二都会消除僵尸之间的一个空隙,所以最多只会进行 \(n-1\) 次操作二。我们只需要枚举进行操作二的次数,对于操作一,反复左右横跳即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+5;
int t,n,k,l,a[N],b[N];
int calc(int x,int lt,int rt)
{
    if(x==0) return 0;
    return max(lt,l-rt)+(x-1)*(lt+l-rt);
}
bool cmp(int x,int y)
{
    return x>y;
}
signed main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>k>>l;
        for(int i=1;i<=n;i++) cin>>a[i];
        sort(a+1,a+1+n);
        for(int i=1;i<=n-1;i++) b[i]=a[i+1]-a[i];
        sort(b+1,b+n,cmp);
        int ans=calc(k,a[1],a[n]),cur=0;
        for(int i=1;i<=min(n-1,k);i++)
        {
            cur+=(b[i]/2);
            a[1]+=(b[i]/2);
            a[n]-=(b[i]/2);
            ans=max(ans,cur+calc(k-i,a[1],a[n]));
        }
        cout<<ans<<'\n';
        for(int i=1;i<=n;i++) a[i]=b[i]=0;
    }
    return 0;
}
posted @ 2026-08-18 14:10  ryderyang  阅读(1)  评论(0)    收藏  举报