CF1928D Lonely Mountain Dungeons

原题链接

\(F(n,m)\) 是将 \(n\) 个同种族的人放到 \(m\) 个队伍中可以获得的贡献。可以发现在同一个队伍中的人不能互相产生贡献,所以尽可能平均分配是最优的。

\(p=\lfloor \dfrac{n}{m}\rfloor,q=n\bmod m\),那么有 \(m-q\) 个队伍中有 \(p\) 个人,\(q\) 个队伍中有 \(p+1\) 个人,贡献是

\[F(n,m)=\dfrac{n(n+1)}{2}-(m-q)\times\dfrac{p(p+1)}{2}-q\times\dfrac{(p+1)(p+2)}{2} \]

\(f_j\) 是分成 \(j\) 个队伍可以获得的贡献,枚举每个种族 \(i\),使 \(f_j\gets f_j+F(c_i,min(j,c_i))\),相当于单点加与后缀加,差分前缀和就行了。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int MAXN=2e5+10;
int T,n,b,z,c[MAXN],f[MAXN],MAX,ans;
inline int F(int x,int y)
{
    int p=x/y,q=x%y;
    return x*(x+1)/2-(y-q)*p*(p+1)/2-q*(p+1)*(p+2)/2;
}
inline void work()
{
    cin>>n>>b>>z;
    for(int i=1;i<=n;++i)
    {
        cin>>c[i];MAX=max(MAX,c[i]);
        for(int j=1;j<c[i];++j)
        {
            int cur=F(c[i],j)*b;
            f[j]+=cur,f[j+1]-=cur;
        }
        f[c[i]]+=F(c[i],c[i])*b;
    }
    for(int i=1;i<=MAX;++i)
        f[i]+=f[i-1],ans=max(ans,f[i]-(i-1)*z);
    for(int i=1;i<=MAX;++i) f[i]=0;
    cout<<ans<<'\n';MAX=ans=0;return ;
}
signed main()
{
    cin.tie(0),cout.tie(0);
    ios::sync_with_stdio(0);
    cin>>T;while(T--) work();
    return 0;
}
posted @ 2024-02-12 17:10  int_R  阅读(38)  评论(0编辑  收藏  举报