UVA 1406 - A Sequence of Numbers(树状数组)

来源:互联网 发布:意大利古典家具 知乎 编辑:程序博客网 时间:2024/06/05 07:25

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;}


1 0