1 条题解
-
0
自动搬运
来自洛谷,原作者为

StudyingFather
在纷繁杂乱的世界里,独自寻找属于自己的光荣与梦想。搬运于
2025-08-24 22:16:33,当前版本为作者最后更新于2020-01-28 19:12:56,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
设 的前缀和为 ,小 Z 取走了前 张牌,小 Y 和小 Z一共取走了 张牌。
则小 Z 的点数为 ,小 Y 的点数为 。
小 Y 为了自己不输,他的点数不能小于小 Z 的点数,但也不能太大(超过上限就不划算了)。最理想的情况是,小 Y 如果少取一张牌,他的点数就小于小 Z 了。
在这种情况下,为了能让小 Z 胜出,只需让上限 小于 就行。
现在问题是对于每个 ,我们需要找到相应的 ,找到了 , 就算出来了。
可以二分找,时间复杂度是 的。
更快的方式是双指针,即移动 的时候,同时将 向右移动,直到 到达我们需要的位置。时间复杂度为 ,比二分的方法更优。
下面是笔者在比赛时写的 的二分做法。
#include <iostream> using namespace std; long long a[1000005],res[1000005]; int main() { ios::sync_with_stdio(false); int n,k,ans=0; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; a[i]+=a[i-1]; } cin>>k; for(int i=1;i<=n;i++) { if(a[i]>=k)break; int p=lower_bound(a+1,a+n+1,2*a[i])-a; if(p==n+1||a[p]-a[i]>k) { res[a[i]]++; res[k+1]--; break; } res[a[i]]++; res[a[p]-a[i]]--; } for(int i=1;i<=k;i++) { res[i]+=res[i-1]; if(res[i])ans++; } cout<<ans<<endl; for(int i=1;i<=k;i++) if(res[i])cout<<i<<' '; return 0; }
- 1
信息
- ID
- 4924
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者