P6013-[CSGRound3]压岁钱【树状数组】

正题

题目链接:https://www.luogu.com.cn/problem/P6013?contestId=25945


题目大意

nnn张牌,玩家111从顶拿若干张,之后玩家222拿若干张。

若牌的和大于KKK那么分数为0否则为牌的和。

KKK为多少时玩家111必胜。


解题思路

我们枚举玩家111拿多少张,然后用一个指针记录玩家222拿到哪里时比玩家111大。若玩家111的和为lll,玩家222刚好比玩家111拿的大时的和为rrr。

那么[l,r1][l,r-1][l,r−1]这个范围都是可以选择的KKK,用树状数组区间覆盖即可。


codecodecode

#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);
}
P6013-[CSGRound3]压岁钱【树状数组】P6013-[CSGRound3]压岁钱【树状数组】 ssl_wyc 发布了867 篇原创文章 · 获赞 55 · 访问量 8万+ 他的留言板 关注
上一篇:python学习之名称空间与作用域


下一篇:2020.02.222日常总结兼【模板】严格次小生成树略讲