hdu 4267 A Simple Problem with Integers

http://acm.hdu.edu.cn/showproblem.php?pid=4267

  一道加强版的树状数组题,利用题目的关键点——除数较小,可以想到将除数跟余数分类,最多分成55种情况,也就是每个结点存放55个数据的的树状数组。

  建树相对简单,遵循思路,直接构建【区间修改,单点查询】的树状数组。就是query的时候比较难想懂,不过明白构树的原理,反过来就可以知道query时要查询那些数据了。在query的时候,只需要将查询的点除以除数得到余数,然后对被查询的数、除数以及余数相应的位置进行树状数组的叠加操作,最后输出结果即可。

1y代码:

View Code
 1 //hdu 4267 BIT by Lyon
 2 
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 
 7 const int maxn = 50005;
 8 typedef __int64 ll;
 9 
10 int node[maxn][11][10];
11 
12 void addSeg(int x, int add, int k, int r){
13     for (; x > 0; x -= x & (-x)) node[x][k][r] += add;
14 }
15 
16 ll query(int x, int end){
17     ll ret = 0;
18 
19     for (int i = 1; i < 11; i++){
20         int r = x % i;
21 
22         for (int t = x; t <= end; t += t & (-t)) ret += node[t][i][r];
23     }
24 
25     return ret;
26 }
27 
28 void deal(int n){
29     for (int i = 1; i <= n; i++){
30         int a;
31 
32         scanf("%d", &a);
33         addSeg(i - 1, -a, 1, 0);
34         addSeg(i, a, 1, 0);
35     }
36 
37     int m;
38 
39     scanf("%d", &m);
40     while (m--){
41         int op;
42 
43         scanf("%d", &op);
44         switch (op){
45             case 1:{
46                 int a, b, k, c;
47 
48                 scanf("%d%d%d%d", &a, &b, &k, &c);
49 
50                 int t = a % k;
51 
52                 addSeg(a - 1, -c, k, t);
53                 addSeg(b, c, k, t);
54             } break;
55             case 2:{
56                 int x;
57 
58                 scanf("%d", &x);
59                 printf("%I64d\n", query(x, n));
60             } break;
61         }
62     }
63 }
64 
65 int main(){
66     int n;
67 
68     while (~scanf("%d", &n)){
69         memset(node, 0, sizeof(node));
70         deal(n);
71     }
72 
73     return 0;
74 }

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/hdu_4267_Lyon.html