1. 程式人生 > >[Codeforces 1058E] Vasya and Good Sequences

[Codeforces 1058E] Vasya and Good Sequences

getchar() https read pla dig style 個數 else int

[題目鏈接]

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

[Codeforces 1058E] Vasya and Good Sequences