codeforces 808D

题意:给出一个序列,询问是否能移动一个数(或不操作)使得序列能分为左右两个和相等的子序列。
思路:对每个数处理最左边和最右边出现的位置。设置断点分左右区间,左右区间和差值的一半就是要找的数,进行判断。

tip:很简单的想法,但debug很久很久,细节部分考虑欠妥。忘记位运算的优先级很低,sub&1==1错误,l[sub]<=i时漏考虑sub不出现时l[sub]都为0,发生错误。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100005;
map<ll,int> l,r;
int a[N];
int main() {
    int n;scanf("%d",&n);
    ll sum=0;
    for(int i=1;i<=n;++i) {
        scanf("%d",&a[i]);
        sum=0ll+sum+a[i];
        if(!l[a[i]]) l[a[i]]=i,r[a[i]]=i;
        else r[a[i]]=i;
    }
    ll t=0;
    int f=0;
    for(int i=1;i<=n && !f;++i) {
        t=0ll+t+a[i];
        ll sub=abs(sum-t-t);
        if(!sub) {
            f=1;break;
        }
        if((sub&1)==1) continue;
        sub/=2ll;
        if(sum-t-t>0&&(r[sub]>i)) f=1;
        else if(sum-t-t<0&&(l[sub]<=i&&l[sub]!=0)) f=1;
    }
    if(f) puts("YES");
    else puts("NO");
    return 0;
}
原文地址:https://www.cnblogs.com/LinesYao/p/6877807.html