HDU 3670 神树状数组(THX 2 ID:Goldbach)

事实证明,我也可以把代码写的像屎一样。

 

这题的关键点是在于把更新操作离线化,对于每次更新,仅仅保存add的值,并不对数列进行修改。

这样就可以保护原数列的性质不变改变。

 

我们先把每一个数拆解成16个后辍

对于每一个后辍num[0...i],若num[i]==0,保存在bit[0][i]中,位置为int(num[0...i])

若num[i]==1,保存在bit[1][i]中,位置为int(num[0...i])

 

在查询与修改操作中,对于每一次修改C a,我们将add+=a

对于Q a,我们分情况讨论。

因为Q a仅仅被add[0...a]这一部分影响,所以我们只需要考虑后辍num[0...a]这一个分支

而int(num[0...a])属于[0,(1<<a)-1]这个区间

设tail==add%(1<<a)

所以当add[a]==1时,我们要找出大小为bit[1]分组中[(1<<a)-tail,1<<(a+1)]的数的数量

以及bit[0]分组中[0...(1<<a)-tail]的数量。

反之也是同样的道理。

原理是在加上这个数之后,此位为1的数,因为在a位进位而使1变0的数会被下一位/几位的进位继续填充为1

此位为0的数,加上a之后,后几位不会再进位。

 

 

View Code
 1 //Result:2012-08-18 14:29:32    Accepted    3670    375MS    8536K    1226 B    C++    Wizmann
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <algorithm>
 7 using namespace std;
 8 const int SIZE=(1<<16)+128,LEN=16;
 9 struct BIT
10 {
11     int baum[SIZE];
12     inline int lowbit(int x){return (x)&(-x);}
13     inline void init(){memset(baum,0,sizeof(baum));}
14     inline void add(int pos,int val){while(pos<SIZE){baum[pos]+=val;pos+=lowbit(pos);}}
15     inline int sum(int pos){int res=0;while(pos>0){res+=baum[pos];pos-=lowbit(pos);}return res;}
16     inline int sum(int a,int b){return sum(b)-sum(a-1);}
17 }bit[2][16];
18 int main()
19 {
20     int n,tmp,cas=1; char cmd[5];
21     long long ans,add;
22     while(scanf("%d",&n)!=EOF && n!=-1)
23     {
24         for(int i=0;i<2;i++) for(int j=0;j<16;j++) bit[i][j].init();
25         for(int i=0;i<n;i++)
26         {
27             scanf("%d",&tmp);
28             for(int j=0;j<LEN;j++) bit[(tmp&(1<<j))==0?0:1][j].add(tmp%(1<<j)+1,1);
29         }
30         add=ans=0;
31         while(1)
32         {
33             scanf("%s",cmd);
34             if(*cmd=='C'){scanf("%d",&tmp);add+=tmp;}
35             else if(*cmd=='Q')
36             {
37                 scanf("%d",&tmp);
38                 int tail=add%(1<<tmp),ptr=(add&(1<<tmp))==0?0:1;
39                 ans+=bit[ptr][tmp].sum((1<<tmp)-tail+1,SIZE-1)+bit[!ptr][tmp].sum(1,(1<<tmp)-tail);
40             }
41             else break;
42         }
43         cout<<"Case "<<cas++<<": "<<ans<<endl;
44     }
45     return 0;
46 }

 

posted on 2012-08-18 14:48  Wizmann  阅读(309)  评论(0编辑  收藏  举报

导航