【HDOJ5975】Aninteresting game(BIT原理)

题意:给定n个区间,第i个区间的范围是[i-lowbit(i)+1,i]。一共有q组询问,询问有两种:

1 x y:询问sigma lowbit(i) (x<=i<=y)

2.x:询问有几个区间包含x这个下标

思路:先打一个lowbit的表找一下规律

考虑第一种询问,能将它拆成两个询问calc(x-1)和calc(y),其中calc(i)表示1到i中lowbit(i)的前缀和

枚举2的幂次,从高位到低位计数,每一个i都只在枚举到lowbit(i)时被算到

考虑第二种询问,树状数组中严格的区间包含(即父子关系)关系只在lowbit左移时出现,所以模拟树状数组更新时的操作,不断往上寻找父节点,计数即可

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<bitset>
 7 typedef long long ll;
 8 using namespace std;
 9 #define N   110000
10 #define oo  10000000
11 #define MOD 1000000007
12 
13 
14 ll lowbit(ll x)
15 {
16     return x&(-x);
17 }
18 
19 ll calc(ll x)
20 {
21     ll ans=0;
22     ll y=1; 
23     while((y<<1)<=x) y<<=1;
24     ll sum=0;
25     while(y)
26     {
27         ans+=y*(x/y-sum);
28         sum+=(x/y-sum);
29         y>>=1;
30     }
31     
32     return ans;
33 }
34 
35 int main()
36 { 
37     ll n;
38     int q;
39     while(scanf("%I64d%d",&n,&q)!=EOF)
40     {
41         for(int i=1;i<=q;i++)
42         {
43             int op;
44             scanf("%d",&op);
45             if(op==1)
46             {
47                 ll x,y;
48                 scanf("%I64d%I64d",&x,&y);
49                 ll ans=calc(y)-calc(x-1);
50                 printf("%I64d\n",ans);
51             }
52              else 
53              {
54                  ll x;
55                  scanf("%I64d",&x);
56                  ll ans=0;
57                  while(x<=n)
58                  {
59                      ans++;
60                      x+=lowbit(x);
61                 }
62                 printf("%I64d\n",ans);
63              }
64                  
65         }
66     }
67     return 0;
68 }
69     

 

posted on 2018-11-20 19:12  myx12345  阅读(127)  评论(0)    收藏  举报

导航