
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Timeclimber/article/details/79980759
A Simple Problem with Integers
Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6241 Accepted Submission(s): 2012
The first line contains an integer N. (1 <= N <= 50000)
The second line contains N numbers which are the initial values of A1, A2, ... , AN. (-10,000,000 <= the initial value of Ai <= 10,000,000)
The third line contains an integer Q. (1 <= Q <= 50000)
Each of the following Q lines represents an operation.
"1 a b k c" means adding c to each of Ai which satisfies a <= i <= b and (i - a) % k == 0. (1 <= a <= b <= N, 1 <= k <= 10, -1,000 <= c <= 1,000)
"2 a" means querying the value of Aa. (1 <= a <= N)
题意:
给了N个数,有一些操作。
操作一是让a到b区间的满足(i-a)%k=0的数,加上c。
操作二是询问位置为I的数为多少。
思路:
借鉴这个http://blog.sina.com.cn/s/blog_a047b3eb010171cc.html
想到树状数组有一种技巧,我们可以对a和b+1两个点单点更新,让a位置+c,b+1位置-c,这样在用树状数组求和的时候,对于a到b的点都是加上了c。所以这样我们让a到b区间无限制的都加上了c,但是我们只想让满足(i-a)%k=0的位置上的点+c。
由(i-a)%k=0可以推出 i%k=a%k,也就是只有当i%k恰好等于a%k时这些数才加上了c。所以我们用树状数组查询的时候,只查满足a%k的数。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=50005; typedef long long ll; int tr[maxn][11][10]; int arr[maxn]; int lowbit(int i) { return i&(-i); } int query(int n) { int sum=0; for(int j=1;j<=10;j++) { for(int i=n;i>0;i-=lowbit(i)) { sum+=tr[i][j][n%j]; } } return sum+arr[n]; } void update(int a,int k,int c,int mod,int n) { for(int i=a;i<=n;i+=lowbit(i)) { tr[i][k][mod]+=c; } } int main() { int n,q,a,b,k,c,op; while(~scanf("%d",&n)) { memset(tr,0,sizeof(tr)); for(int i=1;i<=n;i++) { scanf("%d",&arr[i]); } scanf("%d",&q); for(int i=1;i<=q;i++) { scanf("%d",&op); if(op==2) { scanf("%d",&a); printf("%d\n",query(a)); } else { scanf("%d%d%d%d",&a,&b,&k,&c); update(a,k,c,a%k,n); update(b+1,k,-c,a%k,n); } } } return 0; }