hdu 3670

题意:给出n个数,然后给出m个操作, 操作有两种类型:

       1,将所有的数都加上一个给出的数

       2,求出这n个数中在二进制下第t为是1的数目有多少个(0<=t<=15

最后输出所有询问的和。

思路:这道题想了好久都没有想到。 具体思路是这样的。对于第一种操作, 我们记录当前已经加的和,对于第二问:

我们用16个树状数组, 每一个代表一个后缀。这样的话当询问的时候我们就可以利用 2^(t)<=(x+add)<2^(t+1)求出一个区间。 将区间中元素的数目加起来就行了。

AC代码:

 

View Code
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <string>
 5 using namespace std;
 6 typedef long long LL;
 7 const int N = 65536, M = 101000;
 8 
 9 int p[20][M], n;
10 
11 int lowbit(int t)
12  {
13      return t&(t^(t-1));
14  }
15 
16 int sum(int k, int end)
17  {
18      int ans = 0;
19      end++;
20      while(end > 0)
21       {
22           ans += p[k][end];
23           end -= lowbit(end);
24       }
25      return ans;
26  }
27 
28 void add(int k, int pos, int num)
29  {
30     pos++;
31     while(pos < M)
32      {
33          p[k][pos] += num;
34          pos += lowbit(pos);
35      }
36  }
37 
38 void init()
39  {
40      memset(p, 0, sizeof(p));
41      int w, t;
42      for(int i=1; i<=n; i++)
43       {
44           scanf("%d", &w);
45           t = 0;
46           while(t<16)
47            {
48                add(t,w%(1<<(t+1)),1);
49                t++;
50            }
51       }
52  }
53 
54 void solve(int k)
55  {
56      LL ans = 0;
57      int now = 0;
58      char ss[10];
59      int w, tail;
60      while(scanf("%s", ss) && ss[0] != 'E')
61       {
62           scanf("%d", &w);
63           if(ss[0] == 'C')
64            {
65                now += w;
66                now %= N;
67            }
68           else
69            {
70                tail = now%(1<<w);
71                if(now&(1<<w))
72                 {
73                     ans += sum(w, (1<<w)-tail-1);//0
74                     ans += sum(w, (1<<(w+1))-1) - sum(w,(1<<w+1)-tail-1);
75                 }
76                else
77                 {
78                     ans += sum(w, (1<<(w+1)) - tail-1) - sum(w, (1<<w)-1);
79                     ans += sum(w, (1<<w)-1) - sum(w, (1<<w)-tail-1 );
80                 }
81            }
82       }
83     printf("Case %d: %I64d\n", k, ans);
84  }
85 
86 int main()
87  {
88      int t=0;
89      while(scanf("%d", &n) && n!=-1)
90       {
91           init();
92           t++;
93           solve(t);
94       }
95      return 0;
96  }
posted @ 2012-10-23 14:03  Gu Feiyang  阅读(406)  评论(0)    收藏  举报