正题
题目链接:https://www.luogu.com.cn/problem/P6013?contestId=25945
题目大意
张牌,玩家 从顶拿若干张,之后玩家 拿若干张。
若牌的和大于 那么分数为0否则为牌的和。
求 为多少时玩家 必胜。
解题思路
我们枚举玩家 拿多少张,然后用一个指针记录玩家 拿到哪里时比玩家 大。若玩家 的和为 ,玩家 刚好比玩家 拿的大时的和为 。
那么 这个范围都是可以选择的 ,用树状数组区间覆盖即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define lowbit(x) (x&-x)
using namespace std;
const ll N=1e6+10;
ll n,a[N],t[N],K,ans;
void Change(ll x,ll w){
if(!x) return;
while(x<=K){
t[x]+=w;
x+=lowbit(x);
}
return;
}
ll Ask(ll x){
ll ans=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
scanf("%lld",&n);
for(ll i=1;i<=n;i++)
scanf("%lld",&a[i]);
scanf("%lld",&K);
ll l=2,z=a[1],sum=0;
for(ll i=1;i<=n;i++){
sum+=a[i];z-=a[i];
while(l<=n&&z<sum)
z+=a[l++];
if(sum<z){
Change(sum,1);
Change(z,-1);
}
if(z<sum)
Change(sum,1);
}
for(ll i=1;i<=K;i++)
if(Ask(i)) ans++;
printf("%lld\n",ans);
for(ll i=1;i<=K;i++)
if(Ask(i)) printf("%lld ",i);
}