[题目链接]
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; }
原文地址:https://www.cnblogs.com/evenbao/p/9726874.html
时间: 2024-10-31 13:10:02