Vasya and Good Sequences CodeForces - 1030E

原题链接
考察:思维
思路:
  从样例一很容易想到二进制1的个数一定要为偶数个,但是这样很容易想到反例:1 14,虽然总和也为偶数个但是不成立.这里就延伸出新的规则:1的个数最多的不超过总和的/2.
  总结来说就是:\(sum[r]-sum[l-1]\)为偶,且\(maxn_{l,r}<=\frac{sum}{2}\).
  先考虑优化求偶数区间和.我们用\(sum[i][0/1]\)记录1~i中,sum%2为1,0的个数.那么我们就可以\(O(n)\)算出只考虑前面条件的答案数.
  \(manx<=64\),每个\(a_i\)至少贡献一个1,所以只需要考虑\((i-128,i]\)的最大值.

Code

#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 300010;
int n,cnt[N],sum[N][2],s[N];
LL a[N],res;
LL lowbit(LL x)
{
	return x&-x; 
}
int get(LL x)
{
    int sum = 0;
    while(x)
    {
        sum++;
        x -= lowbit(x);
    }
    return sum;
}
int main()
{
    scanf("%d", &n);
    sum[0][0] = 1;
    for (int i = 1; i <= n;i++)
    {
        scanf("%lld", &a[i]);
        cnt[i] = get(a[i]);
        s[i] = s[i - 1] + cnt[i];
        sum[i][s[i]%2]++;
        sum[i][0] += sum[i - 1][0];
        sum[i][1] += sum[i - 1][1];
        res += sum[i - 1][s[i]%2];
    }
    for (int i = 1; i <= n;i++)
    {
        int l = max(i - 128, 0), maxn = 0;
        for (int j = i - 1; j >= l;j--)
        {
            maxn = max(cnt[j+1], maxn);
            if((s[j]-s[i])%2==0&&maxn>(s[i]-s[j])/2)
                res--;
        }
    }
    printf("%lld\n", res);
    return 0;
}
posted @ 2021-07-09 08:16  acmloser  阅读(40)  评论(0编辑  收藏  举报