树状数组 + 位运算 LA 4013 A Sequence of Numbers

题目传送门

题意:n个数,两种操作,一是每个数字加x,二是查询& (1 << T) == 1 的个数

分析:因为累加是永远的,所以可以离线处理。树状数组点是c[16][M] 表示数字x%(1 << j) 后的数字pos,考虑第j位的个数。当询问时根据add不同的值不同的处理情况。

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

typedef long long ll;
const int N = 1e5 + 5;
const int R = (int) 1 << 16;
const int M = R + 10;
struct BIT  {
    int c[16][M];
    void init(void) {
        memset (c, 0, sizeof (c));
    }
    void updata(int b, int pos) {
        pos++;  //pos 可能等于0
        while (pos < M)   {
            c[b][pos] += 1;
            pos += pos & -pos;
        }
    }
    int sum(int b, int pos) {
        pos++;
        int ret = 0;
        while (pos > 0) {
            ret += c[b][pos];
            pos -= pos & -pos;
        }
        return ret;
    }
}bit;

int main(void)  {
    int n, cas = 0;
    while (scanf ("%d", &n) == 1)   {
        if (n == -1)    break;
        bit.init ();
        for (int x, i=0; i<n; ++i) {
            scanf ("%d", &x);
            for (int j=0; j<16; ++j)    {
                bit.updata (j, x % (1 << (j + 1)));
            }
        }
        ll add = 0, ans = 0; char str[2];
        while (scanf ("%s", &str) == 1) {
            if (str[0] == 'E')  break;
            if (str[0] == 'C')  {       //离线
                int x;  scanf ("%d", &x);
                add += x;
                if (add >= R)   add %= R;
            }
            else    {
                int t;  scanf ("%d", &t);
                int tail = add % (1 << t);
                if (add & (1 << t))    {        //(1<<t)位上已经有1
                    ans += bit.sum (t, (1 << t) - 1 - tail);        //+tail 之前之后,都是0
                    ans += bit.sum (t, (1 << (t + 1)) - 1) - bit.sum (t, (1 << (t + 1)) - 1 - tail);    //+tail 之前1,之后0
                }
                else    {
                    ans += bit.sum (t, (1 << (t + 1)) - 1 - tail) - bit.sum (t, (1 << t) - 1 - tail);   //+tail 之后1
                }
            }
        }
        printf ("Case %d: %lld
", ++cas, ans);
    }

    return 0;
}

  

编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/5221529.html