嘘~ 正在从服务器偷取页面 . . .

洛谷P6015 [CSGRound3]游戏 题解


洛谷P6015 [CSGRound3]游戏 题解

题目链接:P6015 [CSGRound3]游戏

题意

小 Y 和小 Z 是一对好朋友,他们在玩一个游戏。游戏只有一个回合

有一个牌堆,一共有 $n$ 张牌,第 $i$ 张牌上有一个数 $a_i$,其中第一张牌是堆顶。

小 Z 先取牌,他可以从堆顶开始取连续若干张牌(可以取 $0$ 张),取完的牌拿在手上,也就是不在牌堆里了。

然后小 Y 取牌,同样,她也可以从堆顶开始取连续若干张牌(可以取 $0$ 张)。

如果一个人手上的牌的数字和大于 $X$,那么他的分数就是 $0$,否则分数就是数字和。

分数高的人获胜,如果一样高,则无人获胜

小 Z 为了获胜,使用了透视挂,即他知道牌堆里每张牌上写的数。

现在问你对于满足 $1 \leq X \leq K$ 的所有整数 $X$,哪些可以使得小 Z 有必胜策略,即小 Z 取完后,不管小 Y 怎么取都一定会

输入格式

第一行一个整数 $n$,表示牌堆里有几张牌。

第二行 $n$ 个整数 $a_{1\dots n}$,表示每张牌上写的数。

第三行一个正整数 $K$,含义见题目描述。

输出格式

第一行一个整数,表示满足要求的 $X$ 的个数。

第二行从小到大依次输出满足要求的 $X$,用空格隔开。

数据范围

对于 $100\%$ 的数据,$1\leq n,K \leq 10^6$,$1\leq a_i \leq K$。

记 $S_i = \sum _{ j = 1} ^ {i} a_j$ ,$p$ 为所有满足 $S_p - S_i \ge S_i$ 的正整数中最小的一个。

则所有 $X \in \left[S_i, ~S_p - S_i\right)$ 均必胜。则最终答案为所有区间的并。

显然 $p$ 单调不降,因此我们可以以双指针的形式维护它。

时间复杂度 $\mathcal{O}(n)$

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(1e6 + 15))

vector<int> vec;
int n,k,p,X[N * 2 + 15],sum[N];
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n;
    for(int i = 1; i <= n; i++) { cin >> sum[i], sum[i] += sum[i - 1]; }
    cin >> k;
    for(int i = 0; i <= n; i++)
    {
        if(sum[i] > k) break;
        for(; p <= n && sum[p] < sum[i] * 2; ++p) {;}
        ++X[sum[i]]; if(p <= n) --X[sum[p] - sum[i]];
    }
    for(int i = 1; i <= k; i++) {
        if(X[i] += X[i - 1]) vec.emplace_back(i);
    }
    cout << vec.size() << '\n'; for(auto i : vec) cout << i << ' ';
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录