[Codeforces 1058E] Vasya and Good Sequences

[题目链接]

          https://codeforces.com/contest/1058/problem/E

[算法]

        显然 , 我们只需考虑序列中每个数的二进制表示下1的个数即可。 不妨令Ai表示第i个数的二进制表示下1的个数。

        一个子序列[L,R]是“好”的当且仅当 : 

        1. sigma{ Ai }  (L <= i <= R) 为偶数

        2. max{ Ai } (L <= i <= R) <= sigma{ Ai } / 2

        枚举序列左端点L , 可以用后缀和处理R

        时间复杂度 :O(N)

[代码]

         

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 3e5 + 10;

int n;
int cnt[MAXN][2];
int a[MAXN];
long long ans;

template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}

int main()
{
        
        read(n);
        for (int i = 1; i <= n; i++) 
        {
                long long x;
                read(x);
                while (x > 0)
                {
                        a[i] += x & 1;
                        x >>= 1;
                } 
        }
        int suf = 0;
        cnt[n + 1][0] = 1;
        for (int i = n; i >= 1; i--)
        {
                int sum = 0 , mx = 0;
                int add = 0;
                for (int j = i; j <= n && j - i < 65; j++)
                {
                        sum += a[j];
                        mx = max(mx,a[j]);
                        if (sum % 2 == 0 && mx > sum - mx) add--;  
                }
                suf += a[i];
                add += cnt[i + 1][suf & 1];
                ans += add;
                cnt[i][0] = cnt[i + 1][0];
                cnt[i][1] = cnt[i + 1][1];
                if (suf & 1) cnt[i][1]++;
                else cnt[i][0]++;        
        }
        
        printf("%I64d\n",ans);
                
        return 0;
    
}

猜你喜欢

转载自www.cnblogs.com/evenbao/p/9726874.html
今日推荐