1. 程式人生 > 其它 >Vasya and Good Sequences CodeForces - 1030E

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;
}