UVA 1406 - A Sequence of Numbers
题意:给定一些数字,每次操作
C x 表示所有数字加上x
Q x 表示答案加上与2x进行且操作不为0的个数
E 结束,并输出答案
思路:树状数组,首先观察,对于每次查询x而言,只有前x位是是有用的,所以可以开16个树状数组,每个数组表示数字对应前x位下的数字,然后就可以搞了,已经现在加过值为sum,可以推出
2x<=sum+num<2x,这样就可以根据sum来推出num的相应区间,利用区间查询进行查找
代码:
#include <cstdio>
#include <cstring>
#define lowbit(x) (x&(-x))
const int N = 66666;
typedef long long ll;
int n, bit[16][N], mi[20];
void add(int i, int x, int v) {
while (x < N) {
bit[i][x] += v;
x += lowbit(x);
}
}
int get(int i, int x) {
int ans = 0;
while (x) {
ans += bit[i][x];
x -= lowbit(x);
}
return ans;
}
void init() {
memset(bit, 0, sizeof(bit));
int num;
while (n--) {
scanf("%d", &num);
for (int i = 1; i <= 16; i++) {
add(i - 1, num % mi[i] + 1, 1);
}
}
}
ll solve() {
char op[2];
int d, sum = 0;
ll ans = 0;
while (scanf("%s", op)) {
if (op[0] == 'E') break;
scanf("%d", &d);
if (op[0] == 'C')
sum = (sum + d) % mi[16];
else {
int tmp = sum % mi[d];
if (sum&mi[d])
ans += get(d, mi[d] - tmp) + get(d, mi[d + 1]) - get(d, mi[d + 1] - tmp);
else ans += get(d, mi[d + 1] - tmp) - get(d, mi[d] - tmp);
}
}
return ans;
}
int main() {
int cas = 0;
mi[0] = 1;
for (int i = 1; i <= 16; i++)
mi[i] = mi[i - 1] * 2;
while (~scanf("%d", &n) && n != -1) {
init();
printf("Case %d: %lld\n", ++cas, solve());
}
return 0;
}