[CF1030E]Vasya and Good Sequences

解析CF1030E题目“VasyaandGoodSequences”,介绍了一种解决特定序列问题的方法,该问题涉及操作数列元素的二进制位以使区间内元素的异或和为0。通过分析二进制位1的数量,提出了一个时间复杂度为O(60n)的算法。

[CF1030E]Vasya and Good Sequences

题目大意:

给定一个长度为\(n(n\le3\times10^5)\)的数列\(a_i(1\le a_i\le10^{18})\)。可以任意对若干数进行操作,交换这个数的任意二进制位。求有多少区间,使得这个区间内的数经过操作使得异或和为\(0\)

思路:

显然这与\(a_i\)本身的值无关,只与二进制下\(1\)的个数有关。

一个区间\([l,r]\)需要满足以下条件:

  1. 二进制下\(1\)的个数为偶数;
  2. 二进制下\(1\)的个数最多的那个数的\(1\)的个数不超过剩下的数。

对于条件\(1\),我们可以很自然地得到一个\(\mathcal O(n)\)的做法。

对于条件\(2\),由于对于每个数,\(1\)的个数至少是\(1\),最多不超过\(60\),所以只需要枚举\(60\)个即可。

时间复杂度\(\mathcal O(60n)\)

源代码:

#include<cstdio>
#include<cctype>
#include<algorithm>
typedef long long int64;
inline int64 getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int64 x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
const int N=3e5+1;
int c[N],sum[N],cnt[2]={1};
int main() {
    const int n=getint();
    int64 ans=0;
    for(register int i=1;i<=n;i++) {
        c[i]=__builtin_popcountll(getint());
        sum[i]=sum[i-1]+c[i];
        ans+=cnt[sum[i]&1];
        for(register int j=i,k=i+1,max=0;j>=1&&j>=i-61;j--) {
            while(k>j) max=std::max(max,c[--k]);
            if(max*2>sum[i]-sum[j-1]&&(sum[i]%2==sum[j-1]%2)) ans--;
        }
        cnt[sum[i]%2]++;
    }
    printf("%lld\n",ans);
    return 0;
}

转载于:https://www.cnblogs.com/skylee03/p/9740195.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值