思路:开始直接用标记,最后发现他们是离散的点。几乎就相当于单点更行了。欧。
为何放弃治疗。。。
最后看的是 http://blog.csdn.net/ophunter/article/details/9455723
很详细。LCM 最小公倍数学长还是很狂拽酷炫的。
哎。我已可入灵魂。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 50005
#define lson num<<1,s,mid
#define rson num<<1|1,mid+1,e
using namespace std;
int cnt[] = {0,0,1,3,6,10,15,21,28,36,45};//记录每一个K对应的MOD的起点
int n;
int tree[MAXN*3][55];//K(1~10) 每一个K都有0~k-1的mod值 所以就是55棵线段树
void pushdown(int num,int id)
{
if(tree[num][id])
{
tree[num<<1][id]+=tree[num][id];
tree[num<<1|1][id]+=tree[num][id];
tree[num][id]=0;
}
}
void build(int num,int s,int e)
{
memset(tree[num],0,sizeof(tree[num]));
if(s==e)
{
int a;
scanf("%d",&a);
tree[num][0]=a;
return;
}
int mid=(s+e)>>1;
build(lson);
build(rson);
}
void update(int num,int s,int e,int l,int r,int val,int id)
{
if(l<=s && r>=e)
{
tree[num][id]+=val;
return;
}
int mid=(s+e)>>1;
pushdown(num,id);
if(l<=mid)update(lson,l,r,val,id);
if(r>mid)update(rson,l,r,val,id);
}
int query(int num,int s,int e,int tag,int id)
{
if(s==e)
return tree[num][id];
int mid=(s+e)>>1;
pushdown(num,id);
if(tag>mid)return query(rson,tag,id);
else if(tag<=mid)return query(lson,tag,id);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
build(1,1,n);
int op;
scanf("%d",&op);
while(op--)
{
int ope;
scanf("%d",&ope);
if(ope==2)
{
int a,ans=0;
scanf("%d",&a);
for(int i=1;i<=10;i++)
{
int id=cnt[i] + a%i;//(i-a)%k==0 ==> i%k==a%k...
ans+=query(1,1,n,a,id);//线段树上记录的是ADD
}
printf("%d\n",ans);
}
else
{
int a,b,k,c;
scanf("%d%d%d%d",&a,&b,&k,&c);
int id = cnt[k] + a%k;//找到对应的树
update(1,1,n,a,b,c,id);
}
}
}
return 0;
}