USACO24DEC Cake Game S 题解 [ 黄 ] [ 前缀和 ] [ adhoc ]

Cake Game:小清新前缀和题,但是我场上想了半天优先队列贪心假完了 /ll/ll/ll。

观察

本题有三个重要的结论,我们依次进行观察。

不难发现,第二个牛一定会拿 n21 个蛋糕走。同时它拿走的蛋糕一定是左边一段、右边一段。如果它要使自己的分数最大化,那么显然就是要将左边和右边的和最大化。

那么第一头牛有啥用呢,其实根本没用。一个很显然的结论,第一头牛不可能让第二头牛的分数更小,只能让它大于等于原来的分数。证明也很显然,因为这些蛋糕的分数都是正数,合并任何两个蛋糕只会徒增这两个蛋糕的分数,让第二头牛吃到更多的分。

那么第一头牛能不能不让第二头牛多吃任何蛋糕呢?因为第二头牛最多吃 n21 个,所以在博弈过程中我们一定可以取一个中点,然后在中点附近合并,防止它吃到合并后的蛋糕。这个可以自行画图理解。

实现

枚举前一段取了多少,前缀和后缀和计算一下取个最大值就好了。

时间复杂度 O(n)

赛时忘记取蛋糕有后效性,直接优先队列取两边最大值了。我纯唐。

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pi;
int n;
ll a[500005],pre[500005],suf[500005],ans=0;
void solve()
{
    ans=0;
    memset(pre,0,sizeof(pre));
    memset(suf,0,sizeof(suf));
    memset(a,0,sizeof(a));
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)pre[i]=pre[i-1]+a[i];
    for(int i=n;i>=1;i--)suf[i]=suf[i+1]+a[i];
    for(int i=0;i<=n/2-1;i++)
    {
        int l=i,r=n-(n/2-1-i)+1;
        ans=max(ans,pre[l]+suf[r]);
    }
    cout<<pre[n]-ans<<" "<<ans<<'\n';
}
int main()
{
    //freopen("sample.in","r",stdin);
    //freopen("sample.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--)solve();
    return 0;
}
posted @   KS_Fszha  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示