[CF2157D] Billion Players Game 题解

· · 题解

实际上这个绝对值没啥用,先把这个东西去掉,这样对于 a_i 的决策就变成了 \{0,a_i-p,p-a_i\} 选一个。

注意到最终得到的结果实际上是一个关于 p 的一次函数,设为 kp+b,则可以根据 k 的正负分类讨论。

k>0,则求答案时 pl,那么现在的问题就是,对于 i,要从 [0,a_i-l,l-a_i] 中选一个,对应的标记分别为 [0,-1,1],现在要使标记之和 >0,求最大权值。

可以发现标记由 x\to x+1 时,权值的增量为 l-a_i,于是对增量排序然后贪心即可。

::::info[code] ```cpp #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; } ``` ::::