您的位置:首页 > 产品设计 > UI/UE

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

2016-02-26 18:51 453 查看
题目传送门

题意: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\n", ++cas, ans);
}

return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: