题意:N个数(N<=50000),A1~AN,有2种操作,1输出第i个数,2给从第a个到第b个数中(i-a)%k==0的增加一个值c.操作的次数<=50000。
分析:容易想到是线段树。树中每个节点开一个数组add[i][j],保存该区间对%i余j的数增加的值。查询的时候,把查找叶子节点i经过的节点所有对i增加的值累加,加上num[i]即是查询结果。这样更新和查询操作的时间复杂度都是O(nlogn)。
PS:该题容易超内存,开数组时要注意。
1 #include <cstdio>
2 #include <cstring>
3 #define lson l,m,rt<<1
4 #define rson m+1,r,rt<<1|1
5 #define N 50010
6
7 int num[N], add;
8 int mod[N*3][55];
9 int dir[11] = {0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45};
10
11 void update(int l, int r, int rt, int a, int b, int k, int c)
12 {
13 if(l>=a && r<=b)
14 {
15 int tmp = a%k;
16 mod[rt][dir[k]+tmp] += c;
17 return ;
18 }
19 if(l>b || r<a) return ;
20 int m = (l + r) >> 1;
21 update(lson,a,b,k,c);
22 update(rson,a,b,k,c);
23 }
24
25 int query(int l, int r, int rt, int a)
26 {
27 int add = 0;
28 for(int i=1; i<=10; i++)
29 add += mod[rt][dir[i]+a%i];
30 if(l==r)
31 {
32 return add;
33 }
34 int m = (l + r) >> 1;
35 if(a<=m)
36 {
37 return query(lson, a) + add;
38 }
39 else
40 return query(rson, a) + add;
41 }
42
43 int main()
44 {
45 int n, q, type, a, b, k, c;
46 while(scanf("%d",&n)!=EOF)
47 {
48 memset(mod, 0, sizeof(mod));
49 for(int i=1; i<=n; i++)
50 scanf("%d",&num[i]);
51 scanf("%d",&q);
52 for(int i=1; i<=q; i++)
53 {
54 scanf("%d",&type);
55 if(type==2)
56 {
57 scanf("%d",&a);
58 printf("%d ",num[a]+query(1,n,1,a));
59 }
60 else if(type==1)
61 {
62 scanf("%d%d%d%d",&a,&b,&k,&c);
63 update(1,n,1,a,b,k,c);
64 }
65 }
66 }
67 return 0;
68 }
2 #include <cstring>
3 #define lson l,m,rt<<1
4 #define rson m+1,r,rt<<1|1
5 #define N 50010
6
7 int num[N], add;
8 int mod[N*3][55];
9 int dir[11] = {0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45};
10
11 void update(int l, int r, int rt, int a, int b, int k, int c)
12 {
13 if(l>=a && r<=b)
14 {
15 int tmp = a%k;
16 mod[rt][dir[k]+tmp] += c;
17 return ;
18 }
19 if(l>b || r<a) return ;
20 int m = (l + r) >> 1;
21 update(lson,a,b,k,c);
22 update(rson,a,b,k,c);
23 }
24
25 int query(int l, int r, int rt, int a)
26 {
27 int add = 0;
28 for(int i=1; i<=10; i++)
29 add += mod[rt][dir[i]+a%i];
30 if(l==r)
31 {
32 return add;
33 }
34 int m = (l + r) >> 1;
35 if(a<=m)
36 {
37 return query(lson, a) + add;
38 }
39 else
40 return query(rson, a) + add;
41 }
42
43 int main()
44 {
45 int n, q, type, a, b, k, c;
46 while(scanf("%d",&n)!=EOF)
47 {
48 memset(mod, 0, sizeof(mod));
49 for(int i=1; i<=n; i++)
50 scanf("%d",&num[i]);
51 scanf("%d",&q);
52 for(int i=1; i<=q; i++)
53 {
54 scanf("%d",&type);
55 if(type==2)
56 {
57 scanf("%d",&a);
58 printf("%d ",num[a]+query(1,n,1,a));
59 }
60 else if(type==1)
61 {
62 scanf("%d%d%d%d",&a,&b,&k,&c);
63 update(1,n,1,a,b,k,c);
64 }
65 }
66 }
67 return 0;
68 }