转自:
题目:给出n个数,每次将一段区间内满足(i-l)%k==0 (r>=i>=l) 的数ai增加c
http://acm.hdu.edu.cn/showproblem.php?pid=4267
比较容易往线段树上想的。但是由于更新的是一些离散的点,比较麻烦
可以考虑这些点的共性,总是隔几个,更新一个,那窝萌把区间内的数关于k的余数分组
这样每次更新的都是其中的一组,而且是连续的。
由于 K比较小,这是本题的突破口,那么关于k的余数情况,最多只有55种。
即如果k=1,则分为1组,k=2分为2组……
一开始傻叉了打算维护55棵线段树,其实也是可以的,更新只需要1棵,查询是10棵,还是可以接受的。
不过只需要在线段树结点维护这55种情况即可。
不过内存比较紧,要把所有的情况压缩一下,不能开10*10的空间。
同样更新只需要一个,最终统计的话,需要遍历所有的K,也就是最多是10.
1 #include<cstdio>
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 #include<set>
7 #include<map>
8 #include<queue>
9 #include<vector>
10 #include<string>
11 #define Min(a,b) a<b?a:b
12 #define Max(a,b) a>b?a:b
13 #define CL(a,num) memset(a,num,sizeof(a));
14 #define eps 1e-12
15 #define inf 100000000
16 #define mx 10
17
18 const double pi = acos(-1.0);
19 const int maxn = 50100;
20 typedef __int64 ll;
21 using namespace std;
22 struct node
23 {
24 int l;
25 int r;
26 int w;
27 int add[55] ;
28 }p[maxn *4];
29 int a[maxn], b[11][11];
30 void build(int x,int l,int r)
31 {
32 p[x].l = l;
33 p[x].r = r;
34 CL(p[x].add,0);
35 if(l == r)
36 {
37 p[x].w = a[l];
38 return ;
39 }
40 int mid = (l + r)>>1;
41 build(2*x,l,mid);
42 build(2*x+1,mid+ 1,r);
43
44 p[x].w = p[x*2].w + p[x*2+1].w ;
45 }
46 void push_down(int x)
47 {
48 if(p[x].w)
49 {
50 p[x*2].w +=p[x].w;
51 p[x*2+1].w +=p[x].w;
52 p[x].w = 0;
53 for(int i =0 ; i < 55;i++)
54 {
55 p[x*2].add[i] +=p[x].add[i];
56 p[x*2+1].add[i]+=p[x].add[i];
57 p[x].add[i] = 0;
58 }
59 }
60 }
61 void update(int x,int l,int r,int num,int i,int j)
62 {
63 if(p[x].l == l &&p[x].r == r)
64 {
65 p[x].w +=num;
66 p[x].add[b[i][j]]+=num ;
67 return ;
68 }
69 push_down(x);
70 int mid = (p[x].l + p[x].r)>>1 ;
71 if(l > mid)update(x*2+1,l,r,num,i,j);
72 else
73 {
74 if(r<=mid)update(x*2,l,r,num,i,j);
75 else
76 {
77 update(x*2,l,mid,num,i,j);
78 update(x*2+1,mid+1,r,num,i,j);
79 }
80 }
81 }
82 int qury(int x,int pos)
83 {
84 if(p[x].l == pos&&p[x].r == pos)
85 {
86 int tmp = 0;
87 for(int i = 1 ; i <= 10 ;i++)
88 {
89 tmp+=p[x].add[b[i][pos%i]];
90 }
91 return tmp + a[pos] ;
92 }
93 push_down(x) ;
94 int mid = (p[x].l + p[x].r)>> 1;
95 if(pos <= mid) return qury(2*x,pos);
96 else
97 {
98 return qury(x*2+1,pos);
99 }
100 }
101 int main()
102 {
103 freopen("data.txt","r",stdin);
104 int n,s,e,k,c,i,j,q,ty;
105 int cnt = 0;
106 for(i = 1; i<= 10;i++)
107 {
108 for(j = 0;j< i;j++)
109 b[i][j] = cnt++;//由于 内存 卡的紧 ,所以 这样编号 ,不能开 10*10 的
110 }
111 while(scanf("%d",&n)!=EOF)
112 {
113 for(i =1 ; i <=n;i++)
114 {
115 scanf("%d",&a[i]) ;
116 }
117 build(1,1,n);
118 scanf("%d",&q);
119 while(q--)
120 {
121 scanf("%d",&ty);
122 if(ty==1)
123 {
124 scanf("%d%d%d%d",&s,&e,&k,&c);
125 update(1,s,e,c,k,s%k);//这里为什么是 s% k 呢 ,因为 : (i- s)%k = (i%k - s%k + k)%k = 0 的话 ,i%k 应该 = s%k ;
126 }
127 else
128 {
129 int pos;
130 scanf("%d",&pos);
131 int ans = qury(1,pos);
132 printf("%d\n",ans);
133 }
134
135 }
136 }
137 }
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 #include<set>
7 #include<map>
8 #include<queue>
9 #include<vector>
10 #include<string>
11 #define Min(a,b) a<b?a:b
12 #define Max(a,b) a>b?a:b
13 #define CL(a,num) memset(a,num,sizeof(a));
14 #define eps 1e-12
15 #define inf 100000000
16 #define mx 10
17
18 const double pi = acos(-1.0);
19 const int maxn = 50100;
20 typedef __int64 ll;
21 using namespace std;
22 struct node
23 {
24 int l;
25 int r;
26 int w;
27 int add[55] ;
28 }p[maxn *4];
29 int a[maxn], b[11][11];
30 void build(int x,int l,int r)
31 {
32 p[x].l = l;
33 p[x].r = r;
34 CL(p[x].add,0);
35 if(l == r)
36 {
37 p[x].w = a[l];
38 return ;
39 }
40 int mid = (l + r)>>1;
41 build(2*x,l,mid);
42 build(2*x+1,mid+ 1,r);
43
44 p[x].w = p[x*2].w + p[x*2+1].w ;
45 }
46 void push_down(int x)
47 {
48 if(p[x].w)
49 {
50 p[x*2].w +=p[x].w;
51 p[x*2+1].w +=p[x].w;
52 p[x].w = 0;
53 for(int i =0 ; i < 55;i++)
54 {
55 p[x*2].add[i] +=p[x].add[i];
56 p[x*2+1].add[i]+=p[x].add[i];
57 p[x].add[i] = 0;
58 }
59 }
60 }
61 void update(int x,int l,int r,int num,int i,int j)
62 {
63 if(p[x].l == l &&p[x].r == r)
64 {
65 p[x].w +=num;
66 p[x].add[b[i][j]]+=num ;
67 return ;
68 }
69 push_down(x);
70 int mid = (p[x].l + p[x].r)>>1 ;
71 if(l > mid)update(x*2+1,l,r,num,i,j);
72 else
73 {
74 if(r<=mid)update(x*2,l,r,num,i,j);
75 else
76 {
77 update(x*2,l,mid,num,i,j);
78 update(x*2+1,mid+1,r,num,i,j);
79 }
80 }
81 }
82 int qury(int x,int pos)
83 {
84 if(p[x].l == pos&&p[x].r == pos)
85 {
86 int tmp = 0;
87 for(int i = 1 ; i <= 10 ;i++)
88 {
89 tmp+=p[x].add[b[i][pos%i]];
90 }
91 return tmp + a[pos] ;
92 }
93 push_down(x) ;
94 int mid = (p[x].l + p[x].r)>> 1;
95 if(pos <= mid) return qury(2*x,pos);
96 else
97 {
98 return qury(x*2+1,pos);
99 }
100 }
101 int main()
102 {
103 freopen("data.txt","r",stdin);
104 int n,s,e,k,c,i,j,q,ty;
105 int cnt = 0;
106 for(i = 1; i<= 10;i++)
107 {
108 for(j = 0;j< i;j++)
109 b[i][j] = cnt++;//由于 内存 卡的紧 ,所以 这样编号 ,不能开 10*10 的
110 }
111 while(scanf("%d",&n)!=EOF)
112 {
113 for(i =1 ; i <=n;i++)
114 {
115 scanf("%d",&a[i]) ;
116 }
117 build(1,1,n);
118 scanf("%d",&q);
119 while(q--)
120 {
121 scanf("%d",&ty);
122 if(ty==1)
123 {
124 scanf("%d%d%d%d",&s,&e,&k,&c);
125 update(1,s,e,c,k,s%k);//这里为什么是 s% k 呢 ,因为 : (i- s)%k = (i%k - s%k + k)%k = 0 的话 ,i%k 应该 = s%k ;
126 }
127 else
128 {
129 int pos;
130 scanf("%d",&pos);
131 int ans = qury(1,pos);
132 printf("%d\n",ans);
133 }
134
135 }
136 }
137 }