题目:
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)
Output
For each test case, output several lines to answer all query operations.
Sample Input
4
1 1 1 1
14
2 1
2 2
2 3
2 4
1 2 3 1 2
2 1
2 2
2 3
2 4
1 1 4 2 1
2 1
2 2
2 3
2 4
Sample Output
1
1
1
1
1
3
3
1
2
3
4
1
思路:
思路:
区间修改 单点查询
第一个操作是 对在a-b区间内的位置i 如果满足(i-a)%k==0 就把这个位置上的值加上c
式子可以等同于i%k==a%k 所以问题就转化为了右边的部分
从数据范围中可以看到k的范围很小 对k进行枚举
k=1时 可以取的余数为0,1
k=2时 可以取的余数为0,1 ,2
以此类推 所有可以取的结果共55种 根据取余的情况 对这一个区间内该更新哪些线段树进行纪录 然后对这一棵线段树这个区间内的所有值进行更新
代码:
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int maxn=5e4+10;
int n,m,y,a,b,k,c,op,ans;
int x[maxn];
struct node{
int l,r,w;
int add[55];
}tree[maxn<<2];
void build(int l,int r,int rt){
tree[rt].l=l;
tree[rt].r=r;
memset(tree[rt].add,0,sizeof(tree[rt].add));
if(l==r){
tree[rt].w=x[l];
return;
}
int mid=(l+r)/2;
build(l,mid,rt*2);
build(mid+1,r,rt*2+1);
tree[rt].w=tree[rt*2].w+tree[rt*2+1].w;
}
void pushdown(int rt){
tree[rt*2].w+=tree[rt].w;
tree[rt*2+1].w+=tree[rt].w;
tree[rt].w=0;
for(int i=0;i<55;i++){
tree[rt*2].add[i]+=tree[rt].add[i];
tree[rt*2+1].add[i]+=tree[rt].add[i];
tree[rt].add[i]=0;
}
}
void update(int tmp,int rt){
if(tree[rt].l>=a && tree[rt].r<=b){
int index=k*(k-1)/2+tmp;
tree[rt].add[index]+=c;
tree[rt].w+=c;
return;
}
if(tree[rt].w) pushdown(rt);
int mid=(tree[rt].l+tree[rt].r)/2;
if(a<=mid) update(tmp,rt*2);
if(b>mid) update(tmp,rt*2+1);
// tree[rt].w=tree[rt*2].w+tree[rt*2+1].w;
}
void query(int rt){
if(tree[rt].l==y && tree[rt].r==y){
for(int i=1;i<=10;i++){
int index=i*(i-1)/2+y%i;
ans+=tree[rt].add[index];
}
return;
}
if(tree[rt].w) pushdown(rt);
int mid=(tree[rt].l+tree[rt].r)/2;
if(y<=mid) query(rt*2);
else query(rt*2+1);
}
int main(){
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++){
scanf("%d",&x[i]);
}
build(1,n,1);
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d",&op);
if(op==1){
scanf("%d%d%d%d",&a,&b,&k,&c);
update(a%k,1);
}
if(op==2){
ans=0;
scanf("%d",&y);
query(1);
printf("%d
",x[y]+ans);
}
}
}
return 0;
}