OpenJudge 位查询

目录

位查询

要求:

描述:

输入:

输出:

样例输入:

样例输出:

思路分析:

最终代码:


位查询

要求:

总时间限制: 5000ms

内存限制: 65536kB

描述:

  给出N个范围在[0, 65535]的整数,编程支持以下的操作: 

(1)修改操作:C d,所有的数都增加d。如果超过65535,把结果模65536。 0 <= d <= 65535 
(2)查询操作:Q i,统计在N个正整数中有多少个整数其对应的二进制形式的第i位二进制位为非0。0 <= i <= 15。并且最低位i为0。

最后,输出所有查询操作的统计值。

输入:

 输入的第一行为两个正整数N,M,其中N为操作的整数的个数,而M为具体有多少个操作。
输入的第二行为N个正整数,为进行操作的N个正整数。
下面有M行,分别表示M个操作。
N<=100000,M<=200000

输出:

 输出所有查询操作Q的统计值,每一个查询操作统计结果输出为一行。

样例输入:

3 5
1 2 4
Q 1
Q 2
C 1
Q 1
Q 2

样例输出:

1
1
2
1

思路分析:

 这个题目总体来说还是比较简单,在输入中有这样的要求 N\leqslant 100000,M\leqslant 200000 ,看似十分严格,但实际的测试数据好像并没有这么大,所以最朴素的二层循环就可以解决这个问题。

唯一需要注意的点就是在C d的操作中,题目中提到如果超过65536就取模,如果我们采取模运算,实际上是存在不必要的模运算消耗

一个很好的替代品是unsigned short类型,这里需要对不同数据类型有所了解:在x86-64系统中,char型占用1个字节(=8 bits),short型占用2个字节,int型占用4个字节,long型占用8个字节,由于65536=2^{16},所以2字节的short类型可以在溢出的情况下自动取模,又因为不考虑负数,所以unsigned short成为最理想的选择.

位查询有两种方式,一种是将原数右移i位再位与1((num>>i)&1),一种是原数位与左移i位的1(num&(1<<i)),这两种方式都可以,我在代码中采用的是后者.

最终代码:

#include<iostream>
using namespace std;
static int cnt=0;
int main(){
    int N,M;
    scanf("%d%d",&N,&M);
    unsigned short num[N];
    for(int i=0;i<N;i++){
        scanf("%hd",&num[i]);
    }
    for(int i=0;i<M;i++){
        getchar();//读掉行末的回车
        char ch=getchar();
        unsigned short tmp;
        scanf("%hd",&tmp);
        if(ch=='C'){
            for(int j=0;j<N;j++){
                num[j]+=tmp;
            }
        }
        else{
            cnt=0;
            for(int j=0;j<N;j++){
                if(num[j]&(1<<tmp)) cnt++;
            }
            printf("%d\n",cnt);
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值