专栏文章

[CF2157D] Billion Players Game 题解

CF2157D题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min1xymf
此快照首次捕获于
2025/12/01 19:14
3 个月前
此快照最后确认于
2025/12/01 19:14
3 个月前
查看原文
实际上这个绝对值没啥用,先把这个东西去掉,这样对于 aia_i 的决策就变成了 {0,aip,pai}\{0,a_i-p,p-a_i\} 选一个。
注意到最终得到的结果实际上是一个关于 pp 的一次函数,设为 kp+bkp+b,则可以根据 kk 的正负分类讨论。
k>0k>0,则求答案时 ppll,那么现在的问题就是,对于 ii,要从 [0,ail,lai][0,a_i-l,l-a_i] 中选一个,对应的标记分别为 [0,1,1][0,-1,1],现在要使标记之和 >0>0,求最大权值。
可以发现标记由 xx+1x\to x+1 时,权值的增量为 lail-a_i,于是对增量排序然后贪心即可。
k<0k<0 的做法时对称的,对于 k=0k=0 只需要把这个情况加进 k>0,k<0k>0,k<0 任意一个即可。时间复杂度为排序的 O(nlogn)\mathcal{O}(n\log n)
codeCPP
#include<bits/stdc++.h>
#define pb emplace_back
#define pob pop_back
#define mp make_pair
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const ll maxn=1000007,ee=1e18;
ll n,l,r,a[maxn];
vector<ll> vec;
ll solve1(ll x){
    ll cur=0;
    vec.clear();
    for(ll i=1;i<=n;i++) cur+=a[i]-x,vec.pb(x-a[i]),vec.pb(x-a[i]);
    sort(vec.begin(),vec.end(),greater<ll>());
    for(ll i=0;i<n;i++) cur+=vec[i];
    for(ll i=n;i<2*n;i++)if(vec[i]>=0) cur+=vec[i];
    return cur;
}
ll solve2(ll x){
    ll cur=0;
    vec.clear();
    for(ll i=1;i<=n;i++) cur+=x-a[i],vec.pb(a[i]-x),vec.pb(a[i]-x);
    sort(vec.begin(),vec.end(),greater<ll>());
    for(ll i=0;i<n;i++) cur+=vec[i];
    for(ll i=n;i<2*n;i++)if(vec[i]>=0) cur+=vec[i];
    return cur;
}
int main(void){
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    ll T=1; cin>>T;
    for(;T--;){
        cin>>n>>l>>r;
        for(ll i=1;i<=n;i++) cin>>a[i];
        cout<<max(solve1(l),solve2(r))<<"\n";
    }
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...