题目大意:解释起来有些麻烦,直接贴一下英文版好了
Problem Description
Let A1, A2, ... , AN be N elements. You need to deal with two kinds of operations. One type of operation is to add a given number to a few numbers in a given interval. The other is to query the value of some element.
Input
There are a lot of test cases.
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)
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)
如果k只能等于1,那么这就是一道很简单的题,对于每个操作1 a b 1 c,只需要将p[a] += c,p[b+1] -= c。对于查询2 x,只要统计p[1]+p[2]+p[3]+.......p[x-1]+p[x]的值就好了。
由此出发,可以发现这一题的k并不大,仅仅只有10,这样就可以对每个k做一种维护
具体做法是:
对于每个操作1 a b k c
h[k][a] += c, h[k][u] -= c , (u-a)%k == 0 且 u > b 且 u-k < b
对于每个查询2 x
就需要统计
h[1][x] + h[1][x-1] + ..... + h[1][1] +
h[2][x] + h[2][x-2] + ...... + h[2][x%2+2] + h[2][x%2] +
.......
h[10][x] + h[10][x-10] + ....... + h[10][x%10+10] + h[10][x%10]
+a[x]
这个可以使用树状数组来维护,只是在树状数组维护的过程中需要进行一个下标的转换:
我的树状数组维护的代码:
int trans(int x, int k)
{
x = x / k + 1;
return x;
}
int _trans(int x, int k, int p)
{
x = (x - 1) * k + p;
return x;
}
int lowbit(int x)
{
return x&(-x);
}
int add1(int x, int k)
{
int p;
p = x % k;
x = trans(x, k);
x += lowbit(x);
x = _trans(x, k, p);
return x;
}
int sub1(int x, int k)
{
int p;
p = x % k;
x = trans(x, k);
x -= lowbit(x);
if (x == 0)
return 0;
x = _trans(x, k, p);
return x;
}
int query_k(int x, int k)
{
int ans = 0;
while (x > 0)
{
ans += h[k][x];
x = sub1(x, k);
}
return ans;
}
void updata(int x, int k, int val)
{
while (x <= n)
{
h[k][x] += val;
x = add1(x, k);
}
}
最后附上这一题全部的代码:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
const int MAXM = 15;
const int MAXN = 6e4;
int h[MAXM][MAXN], a[MAXN];
int n, m;
int trans(int x, int k)
{
x = x / k + 1;
return x;
}
int _trans(int x, int k, int p)
{
x = (x - 1) * k + p;
return x;
}
int lowbit(int x)
{
return x&(-x);
}
int add1(int x, int k)
{
int p;
p = x % k;
x = trans(x, k);
x += lowbit(x);
x = _trans(x, k, p);
return x;
}
int sub1(int x, int k)
{
int p;
p = x % k;
x = trans(x, k);
x -= lowbit(x);
if (x == 0)
return 0;
x = _trans(x, k, p);
return x;
}
int query_k(int x, int k)
{
int ans = 0;
while (x > 0)
{
ans += h[k][x];
x = sub1(x, k);
}
return ans;
}
void updata(int x, int k, int val)
{
while (x <= n)
{
h[k][x] += val;
x = add1(x, k);
}
}
int query(int x)
{
int i, ans = 0;
for (i=1; i<=10; i++)
ans += query_k(x, i);
return ans;
}
int main()
{
int i, j, x, y, k, c, tt, ans, ll;
while (scanf("%d",&n)!=EOF)
{
for (i=0; i<=n; i++)
for (j=1; j<=10; j++)
h[j][i] = 0;
for (i=1; i<=n; i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for (i=0; i<m; i++)
{
scanf("%d",&tt);
if (tt == 1)
{
scanf("%d%d%d%d",&x,&y,&k,&c);
updata(x, k, c);
ll = x + (y - x) / k * k;
while (ll <= y) ll += k;
updata(ll, k, -1*c);
}
else if (tt == 2)
{
scanf("%d",&x);
ans = query(x) + a[x];
printf("%d\n",ans);
}
}
}
return 0;
}