uva1406 - A Sequence of Numbers 树状数组

You are given a sequence of N integers (each within the range [0, 216 - 1]) along with P operations and in order to solve this problem you need to process the operations instructed as follows.

There are two kinds of operations that you will be instructed to perform:

1) Modification
- Given a non-negative number T, you need to increase the value of every number in the sequence by T. If the value of any number in the sequence is larger than 216 - 1 after the operation, you should divide its value by 216 and take the remainder as its value;
2) Query
- Given a non-negative number T, query how many numbers in the sequence satisfies the condition that its bitwise and result with 2T is greater than zero.

For simplicity, all you need to do here is to output the sum (sum < 10, 000, 000, 000) of the answers to all queries.

Input 

There are multiple test cases in the input file. Each test case starts with one integer N (N$ \le$105), the number of integers in the sequence. The following N line consists of one integer P (0$ \le$P$ \le$216 - 1), the value on i-th line being the value of the i-th number in the sequence.

Each of the following lines is either of the format ``C delta" (0$ \le$delta), meaning that you should increase the value of every number by delta, or ``Q i" (0$ \le$i$ \le$15), meaning that you should calculate the answer to the query (as explained in the problem description). Every test case ends with one character `E' on a single line, followed by a blank line.

N = - 1 indicates the end of input file and should not be processed by your program. It is guaranteed that the total number of operations in each test case does not exceed 200,000.

Output 

For each test case, print the sum of answers to queries on one separate line in the format as indicated in the sample output.

Sample Input 

3 
1 
2 
4 
Q 1 
Q 2 
C 1 
Q 1 
Q 2
E

-1

Sample Output 

Case 1: 5

  两种操作,Q询问所有数中与上2^t大于0的有多少个(其实就是t那一位为1的有多少个),C是把所有数加上t。最后输出所有询问的和。

  开16个树状数组,第i个树状数组保存所有数对2^(i+1)取余的结果,也就是对每个数只保留低i位。用cnt记录C操作的和,询问的时候tmp=cnt%(2^i),如果cnt&2^i为0,那么答案就是所有加上tmp后第i位为1的数,sum(c[t],power[t+1]-tmp)-sum(c[t],power[t]-tmp)。如果cnt&2^i为1,答案就是所有加上tmp后第i位为0的数,等于总数减去刚才的。

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<algorithm>
#define INF 0x3f3f3f3f
#define eps 1e-9
#define MAXNODE 105
#define MOD 10000007
#define SIGMA_SIZE 4
typedef long long LL;
using namespace std;

const LL MAXN=66000;
const LL MAXM=110;

LL N,M,power[20],c[20][MAXN];

void init(){
    power[0]=1;
    for(LL i=1;i<=16;i++) power[i]=power[i-1]*2;
}

LL lowbit(LL x){
    return x&(-x);
}

LL add(LL* c,LL i,LL v){
    while(i<MAXN){
        c[i]+=v;
        i+=lowbit(i);
    }
}

LL sum(LL* c,LL i){
    LL ret=0;
    while(i>0){
        ret+=c[i];
        i-=lowbit(i);
    }
    return ret;
}

int main(){
    freopen("in.txt","r",stdin);
    LL cas=0;
    init();
    while(scanf("%lld",&N)!=EOF&&N!=-1){
        memset(c,0,sizeof(c));
        for(LL i=0;i<N;i++){
            LL t;
            scanf("%lld",&t);
            for(LL j=0;j<=15;j++) add(c[j],t%power[j+1]+1,1);
        }
        char str[10];
        LL cnt=0,ans=0;
        while(scanf("%s",str),str[0]!='E'){
            LL t;
            scanf("%lld",&t);
            if(str[0]=='C') cnt=(cnt+t)%power[16];
            else{
                LL tmp=cnt%power[t];
                if(cnt&power[t]) ans+=sum(c[t],power[t+1])-(sum(c[t],power[t+1]-tmp)-sum(c[t],power[t]-tmp));
                else ans+=sum(c[t],power[t+1]-tmp)-sum(c[t],power[t]-tmp);
            }
        }
        printf("Case %lld: %lld\n",++cas,ans);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值