cf1058E 思维 前缀处理

题目大意:给定一个长度为 (n≤3×105)的数列ai(1≤ai≤1018)交换一个数的任意二进制位,问你可以选出多少 区间经过操作后异或和是 0

链接:http://codeforces.com/contest/1058/problem/E

思路:由于二进制随意交换,那么它本身值不必考虑,只需要保存它有多少二进制为1的个数就好了。

充分必要条件:

  • 区间中二进制1的个数是偶数
  • 区间中二进制位最多的一个数的二进制个数小于等于和的一半

对于条件一 

所以前面的为偶数的前提下  , 根据(0,l)的奇偶性 来判断 (l,r)的奇偶性  所以 ,将所有前缀和的奇偶性统计出来  O(n)的负责度

暂且将条件一全加上  然后再在条件二中减去

因为ai <1e18 >1 的限制所以枚举大约60位 就可以截至

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define pb push_back
#define fi first
#define se second
#define all(v) v.begin(),v.end()
#define forn(i,a,n) for(int i=a;i<n;++i)

const int N = 3e5+4;
ll a[N],b[N];

ll cbit(ll x){
    ll res=1;
    while(x){
        if(x&1)res++;
        x/=2;
    }
    return res-1;
}
ll sum[N];
int cnt[2];

int main(){

    int n;
    cin>>n;
    forn(i,1,n+1){
        scanf("%lld",a+i);
        b[i]= cbit(a[i]);
    }
    ll ans=0 ;

      cnt[0]=1;

    //1 (1..j-1) , j  为偶数   // 这里用公式说明一下
    forn(i,1,n+1){
        sum[i] = sum[i-1]+b[i];
        ans += cnt[sum[i]&1]; //1 (0..j) , j  为偶数   // 这里用公式说明一下

        //根据条件2 倒着减过去
        int j =i,k=i;
        ll  Max = b[i];

        while(k>=1 && j-k<=62 ){
            Max = max(Max,b[k]);
           if(  Max*2 > sum[i]-sum[k-1] && ( (sum[i]-sum[k-1] )%2==0 )  )ans--;
           k--;
        }
        cnt[sum[i]&1]++;
        //cout<<ans<<endl;

    }

    cout<<ans<<endl;

    return 0;
}

---恢复内容结束---

原文地址:https://www.cnblogs.com/wjhstudy/p/9744816.html

时间: 2024-10-21 00:27:35

cf1058E 思维 前缀处理的相关文章

Spotlights【思维+前缀和优化】

https://blog.csdn.net/mengxiang000000/article/details/53291883   原博客地址 http://codeforces.com/group/1EzrFFyOc0/contest/738/problem/B  题目链接 题目大意: 给你一个N*M的空间,其中0表示没有人,1表示有人,对应一个好位子以及方向的定义为: ①首先这个位子不能有人. ②其次对应这个位子安排一个照明方向,这个方向上必须有人才行. 让你求一共有多少个这样满足的放置方案.

Covered Points Count CF1000C 思维 前缀和 贪心

Covered Points Count time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output You are given nn segments on a coordinate line; each endpoint of every segment has integer coordinates. Some segments c

AtCoder Beginner Contest 124 D - Handstand(思维+前缀和)

D - Handstand Time Limit: 2 sec / Memory Limit: 1024 MB Score : 400400 points Problem Statement NN people are arranged in a row from left to right. You are given a string SS of length NN consisting of 0 and 1, and a positive integer KK. The ii-th per

Codeforces 873 B. Balanced Substring(前缀和 思维)

题目链接: Balanced Substring 题意: 求一个只有1和0的字符串中1与0个数相同的子串的最大长度. 题解: 我的解法是设1的权值是1,设0的权值是-1,求整个字符串的前缀和并记录每个前缀和出现的最后位置.因为两个相同的前缀和之间的子串一定符合条件,最后只用遍历一次,将每个前缀与和这个前缀值相同的位置之间的长度求出来就是符合条件的子串长度.但是这里一定要注意!在整个子串未开始遍历的时候这个子串的前缀和也是0.我就是在这个地方错了,这里给出错地方的数据. 1 #include<bi

【P2879】 [USACO07JAN]区间统计Tallest Cow {前缀和,思维}

思路: 先初始化所有牛的身高为0. 对于每一个约束条件(a,b)我们将a+1 ~ b-1的牛的身高全部减一. 朴素的减是TLE的,所以我们维护一个前缀和数组d[]来搞,对于约束条件(a,b)我们将d[a+1]--,将d[b]++. 碎碎念: 这个思路很明白,但是为什么是正确的(尤其是为什么每次减一不会产生矛盾)?我把luogu的题解浏览了一遍也没有看到证明. 所以我就自己证了一下.有两种证明方法: 一是循环不变式(算法导论上有很漂亮的例子),证起来很清晰. 二是反证法:假设有一组约束条件必须减>

HDU 6276 Easy h-index(思维+二分/前缀和)

题意字面理解:求最大的h,使得至少有h篇文章被发表并且每篇文章都至少有h个引用 进一步翻译:给定一个数组,求$h_{max}$,使得$\sum_{i=index}^{n}a_{i}\geq h_{max}$ 第一种思路,也是我一开始的思路(Onlgn): 二分答案,求$\sum_{i=mid}^{n}a_{i}$,记为sum,记录mid,若满足sum>=h,向右区间继续二分:反之向左区间二分. 两种二分写法都可: int get(int a[], int n)//[l, r) {int ans=

CF 1196D2 RGB Substring (hard version) --- 前缀和 + 思维

简单的情况不用前缀和,直接暴力就好,数据范围大的D2,就用前缀和数组存不满足三种情况的数,最后减一下取小就可以. 1 #include<bits/stdc++.h> 2 #define mem(a) memset(a,0,sizeof(a)) 3 #define ll long long 4 #define ld long double 5 #define ull unsigned long long 6 #define mp make_pair 7 #define pb push_back

Codeforces Round #400 C 前缀和,思维

ICM Technex 2017 and Codeforces Round #400 (Div. 1 + Div. 2, combined) C. Molly's Chemicals 题意:n个数,问有多少个区间的和是k的次方数,即sum([l, r])=k^x, x>=0. abs(k)<=10. tags:一开始O(n^2)统计,果然炸了.. 这题要在统计到第 i 个数时,看s[i]-k^x是否在前面出现过.因为k指数增长很快,这样就是O(n). // #400 #include<b

Color the ball 前缀和+思维

Color the ball N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色.但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗? Input每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <= N). 当N = 0