给你一个序列,问你是否可以只移动一个数(或者不移动),使其一个前缀和或者后缀和为 总和的一半。
方法1 :二分枚举那个数,分别从前从后。
注意二分查找的范围。
不能超过i
方法2 set
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn=100009;
/*这道题其实再加把劲我感觉还是能写掉的。。
只是一直想写e题。结果e题也没写,这道题也没写。
给你一些数,问你是否可以通过移动一个数(或者不移动),让这些数的和是总和的二分之一。
这道题也为k字段和提供了思路,
可以通过枚举前缀串(和后缀),然后
*/
int main()
{ int m;
long long sum[maxn];
int a[maxn];
bool flag=false;
scanf("%d",&m);
sum[0]=0;
for(int i=1;i<=m;i++)
{ scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
if(sum[m]%2!=0)
{ puts("NO");
return 0;
}
long long num=sum[m]/2;
for(int i=1;i<=m;i++)
{ int l=lower_bound(sum,sum+i-1,num-a[i])-sum;
if(sum[l]+a[i]==num)
{ flag=true;
break;
}
}
reverse(a+1,a+m+1);
sum[0]=0;
for(int i=1;i<=m;i++)
sum[i]=sum[i-1]+a[i];
for(int i=1;i<=m;i++)
{ int k=lower_bound(sum,sum+i-1,num-a[i])-sum;
if(sum[k]+a[i]==num)
{ flag=true;
break;
}
}
if(flag)
puts("YES");
else
puts("NO");
return 0;
}
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
using namespace std;
#define _ ios::sync_with_stdio(false)
const int MAXN = 100010;
const int INF=0x7fffffff;
long long a[MAXN];
long long sum=0;
long long s1[MAXN];
set<long long > s;
int main(){
int n;
scanf("%d",&n);
s1[0]=0;
for(int i=1;i<=n;i++){
scanf("%lld",a+i);
sum+=a[i];
s1[i]=s1[i-1]+a[i];
}
int ok=0;
s.clear();
for(int i=1;i<=n;i++){
if(s.count(2*a[i])){
ok=1;
break;
}
long long x=sum-2*s1[i];
if(x==0){
ok=1;
break;
}
if(x>=0)
s.insert(x);
}
s.clear();
for(int i=n;i>=1;i--){
if(s.count(2*a[i])){
ok=1;
break;
}
long long x=2*s1[i]-sum;
if(x==0){
ok=1;
break;
}
if(x>=0)
s.insert(x);
}
if(ok)
puts("YES");
else
puts("NO");
}