Codeforces Round #640 (Div. 4) D. Alice, Bob and Candies

Codeforces Round #640 (Div. 4)

翻译 岛田小雅

D. Alice, Bob and Candies

出题人 MikeMirzayanov

\(n\) 个糖果排成一排,从左到右分别被编号为 \(1\)\(n\)。第 \(i\) 个糖果的体积是 \(a_i\)

Alice 和 Bob 在一个既有趣又美味的游戏:他们按照排列顺序吃糖。Alice 从左边开始吃,Bob 从右边开始吃。所有的糖被吃完时,游戏结束。

他们是轮流行动的。在一次行动中,轮到的玩家吃掉 TA 应该吃掉的糖果。

Alice 先手,第一次行动,她吃掉左边的 \(1\) 颗糖果(体积是 \(a_1\))。接下来,每次一个人成功吃掉一组糖果,就轮到另一个人吃。比如 Alice 吃完第一个糖果后,第二次行动由 Bob 吃掉右边的一组糖果,然后再轮到 Alice,然后再是 Bob……

每次行动,当前回合玩家在吃每颗糖前会计算 TA 本轮已经吃掉的糖果的总体积。如果 TA 已经吃掉的糖果总体积严格大于另外一个人的,那 TA 就结束行动。换句话说,每次行动的玩家都会吃尽量少的糖让自己这次吃掉的总体积严格大于另一个玩家上次行动时吃掉的的总体积。如果糖果不足,就吃掉剩下的所有糖果。

举个例子,如果 \(n=11\) 并且 \(a=[3,1,4,1,5,9,2,6,5,3,5]\),那么:

  • 行动 \(1\):Alice 吃掉左边第一颗体积为 \(3\) 的糖果,数组变成 \([1,4,1,5,9,2,6,5,3,5]\)
  • 行动 \(2\):Alice 上一轮吃掉的糖果体积是 \(3\),Bob 本轮吃掉大于等于 \(4\) 体积的糖果才能结束行动。Bob 这次行动吃掉最右边的一颗体积为 \(5\) 的糖果,这样数组变成 \([1,4,1,5,9,2,6,5,3]\)
  • 行动 \(3\):Bob 上一轮吃掉了 \(5\) 体积糖果,那 Alice 本轮就要吃掉 \(6\) 体积或更多。她吃掉左边的 \(3\) 颗糖果,体积为 \(1+4+1=6\),数组变成 \([5,9,2,6,5,3]\)
  • 行动 \(4\):Alice 上一轮吃掉了 \(6\) 体积糖果,那 Bob 本轮就要吃掉 7 体积或更多。他吃掉右边的 \(2\) 颗糖果,体积为 \(3+5=8\),数组变成 \([5,9,2,6]\)
  • 行动 \(5\):Bob 上一轮吃掉了 \(8\) 体积的糖果,那 Alice 这一回合要吃掉 \(9\) 体积或更多。她吃掉右边的 \(2\) 颗糖果,体积为 \(5+9=14\),数组变成 \([2,6]\)
  • 行动 \(6\)(最终行动):Alice 上一轮吃掉了 \(14\) 体积的糖果,而剩下的糖果总体积为 \(8\),小于 \(15\),所以 Bob 吃掉剩下所有的糖果,游戏结束。

输出游戏的轮数和两个数字:

  • 数字 \(a\) 表示在游戏过程中 Alice 吃掉的所有糖果的体积。
  • 数字 \(b\) 表示在游戏过程中 Bob 吃掉的所有糖果的体积。

输入格式

第一行是一个整型 \(t\) \((1\leqslant{t}\leqslant{5000})\),表示测试点数目。接下来是对测试点的描述。

每一个测试点包括两行,第一行是一个整型 \(n\) \((1\leqslant{n}\leqslant{1000})\) 代表糖果的总数。第二行有一个数组 \(a_1,a_2,…,a_n\) \((1\leqslant{a_i}\leqslant{1000})\),从左到右表示每一颗糖果的体积。

数据保证 \(n\) 的总和不超过 \(2·10^5\)

输出格式

对每个测试点输出一行 \(3\) 个整型,分别表示游戏轮数和数字 \(a\)\(b\)

样例

输入

7
11
3 1 4 1 5 9 2 6 5 3 5
1
1000
3
1 1 1
13
1 2 3 4 5 6 7 8 9 10 11 12 13
2
2 1
6
1 1 1 1 1 1
7
1 1 1 1 1 1 1

输出

6 23 21
1 1000 0
2 1 2
6 45 46
2 2 1
3 4 2
4 4 3

题解

作者 岛田小雅

这题为什么能有 1300 分我不理解。

\(n\) 总和不超过 \(2·10^5\),考虑直接暴力模拟。

除了用数组以外,这里我想整个活玩一下 \(\texttt{deque}\) 容器。

\(\texttt{deque}\) 容器支持双端快速插入及删除元素。我们用一个 \(\texttt{deque}\) 存储当前测试点的糖果体积,游戏过程中被吃掉的就丢出去。

详情见 AC 代码。

AC 代码

作者 岛田小雅
#include <bits/stdc++.h>
using namespace std;

int t, n, sum;
int last, alice, bob, rounds, ate;
bool turn; // false轮到bob,true轮到alice

int main()
{
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> t;
    while(t--)
    {
        deque<int> q;
        sum = alice = bob = rounds = 0;
        cin >> n;
        for(int i = 1; i <= n; i++)
        {
            int tmp;
            cin >> tmp;
            sum += tmp;
            q.push_back(tmp);
        }
        rounds++;
        ate = q.front();
        sum -= q.front();
        q.pop_front();
        last = ate;
        alice += ate;
        turn = false;
        while(!q.empty())
        {
            rounds++;
            ate = 0;
            if(sum <= last)
            {
                ate = sum;
                sum = 0;
                q.clear();
            }
            else while(ate <= last)
            {
                if(turn)
                {
                    ate += q.front();
                    sum -= q.front();
                    q.pop_front();
                }
                else
                {
                    ate += q.back();
                    sum -= q.back();
                    q.pop_back();
                }
            }
            last = ate;
            if(turn) alice += ate;
            else bob += ate;
            turn = !turn;
        }
        cout << rounds << ' ' << alice << ' ' << bob << '\n';
    }    
    return 0;
}
posted @ 2022-09-23 18:15  岛田小雅  阅读(22)  评论(0编辑  收藏  举报