CodeForces-808#D 题解
思路分析
分析样例 1:
3 1 3 2
原数组被分成 1
和 3 2
两部分,将 2
移到左边即可。
我们设左边部分的和为
推论 1:由于
推论 2:只有当
我们枚举
但真的如此吗?
考虑下面的样例:
5 1 2 2 5 4
这本来应该是 NO
的,但如果你只按照上述所说很有可能会输出 YES
。
按照上面所述,你的程序在将原数列分割成 1 2 2
和 5 4
时,
再仔细看看样例,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
,你会后悔的,警钟长鸣。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步