Codeforces - 1053 - B. Vasya and Good Sequences
阿新 • • 發佈:2018-11-10
題目連結<http://codeforces.com/contest/1053/problem/B>
題意:
定義一個操作:把數字中的兩位進行交換。給出一個序列,問存在多少個子區間,對區間內的數字進行無限次操作後使得區間內數字的異或和為0。計算符合條件的區間數。
題解:
如果一個區間內1的個數和為奇數那一定不可取。
對於偶數的情況,如果1的個數最大的數小於等於其餘數字之和,就一定能構造出來。
因為數字的範圍是1e18,所以1的個數不超過60。對於區間長度不超過60的可以直接暴力,超過的可以預處理字首和的奇偶來計算sum是偶數的個數。
#include<bits/stdc++.h> using namespace std; #define ll long long const ll N=3e5+7; ll n,a[N],sum[N],cnt[N][2]; ll x; ll get(ll x){ ll res=0; while(x){ if(x&1) res++; x>>=1; } return res; } int main() { scanf("%lld",&n); for(ll i=1;i<=n;i++){ scanf("%lld",&x); a[i]=get(x); sum[i]=sum[i-1]+a[i]; } for(ll i=n;i>=1;i--){ cnt[i][0]=cnt[i+1][0]; cnt[i][1]=cnt[i+1][1]; if(sum[i]%2) cnt[i][1]++; else cnt[i][0]++; } ll ans=0; for(ll i=1;i<=n;i++){ ll len=min(i+60,n); ll maxn=a[i]; for(ll j=i+1;j<=len;j++){ maxn=max(maxn,a[j]); if((sum[j]-sum[i-1]-maxn>=maxn)&&((sum[j]-sum[i-1])%2==0)) ans++; } ans+=cnt[len+1][sum[i-1]%2]; } printf("%lld\n",ans); }