一叹世间情太苦,为爱|

IOIAK_wanguan

园龄:2年6个月粉丝:2关注:0

2024-08-03 19:16阅读: 9评论: 0推荐: 0

CodeForces-808#D 题解

思路分析

分析样例 1:

3
1 3 2

原数组被分成 13 2 两部分,将 2 移到左边即可。

我们设左边部分的和为 s1,右边为 s2,可以发现对于任何分割方式,只有满足 s1±x=s2x 才可以继续讨论答案是否成立。

推论 1:由于 xaa 为题目所给数列),因此 | s1s2 |0 (mod 2 )(换句话说,s1s2 的差值必然是偶数)。

推论 2:只有当 | s1s2 |2a 时,才能成立。

我们枚举 p{0 , n+1},得出区间 a[ 1 , p ]a[ p+1 , n ] 之和,根据以上推论编写代码,可以用桶查询 | s1s2 |2 是否在原数列。

但真的如此吗?

考虑下面的样例:

5
1 2 2 5 4

这本来应该是 NO 的,但如果你只按照上述所说很有可能会输出 YES

按照上面所述,你的程序在将原数列分割成 1 2 25 4 时,| s1s2 |2 为 2,而 2 在桶中是可以被找到的,也就是说,你的程序认为从右边可以往左边移动一个 2,这样就成立了。

再仔细看看样例,2 分明在左边,右边是没有 2 的。

没错,你还要判断当应该从某一边移动数字时,你要判断该数字是否在这一边。

以上就是本道题的思路。如若存在常识性错误,请踢本蒟蒻。

代码实现

#define by_wanguan
#include<iostream>
#include<map>
#include<vector>
#define int long long
#define pb emplace_back
#define end cout<<"YES",exit(0)
using namespace std;
const int N=1e5+7;
int n,a[N],sum,p,s1,s2;
map<int,vector<int>> vis;
inline int abs(int &a,int &b){
if(a>b) return a-b;
else return b-a;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i],sum+=a[i],vis[a[i]].pb(i);
//记录a中a[i]出现的位置,方便后续判断abs(s2-s1)/2是否在区间内
s2=sum,s1=0;
for(p=0;p<=n+1;p++){//枚举左右区间分界线
s1+=a[p],s2-=a[p];
if(abs(s2-s1)%2!=0) continue;
if(s1==s2) end;
auto &pe=vis[abs(s2-s1)/2];
if(s1<s2)
{if(!pe.empty()&&pe.back()>p) end;}
//由于上面的位置记录时单调的,只需要取最靠后面的位置就能判断右区间内是否有abs(s2-s1)/2
//下面同理
if(s1>s2)
{if(!pe.empty()&&pe.front()<=p) end;}
}
cout<<"NO";
}

千万不要用 unordered_map,你会后悔的,警钟长鸣。

喵。

本文作者:wanguan

本文链接:https://www.cnblogs.com/wanguan/p/18340922

版权声明:本作品采用 BY-NC-SA 4.0 许可协议进行许可。

posted @   IOIAK_wanguan  阅读(9)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起