题意
给定
个数,实现两种操作:对一个区间中的数加上一个值,询问一个区间所有数的和。
思路
对于区间修改查询,分块和线段树均能方便的实现,模板题不讲了。
代码
分块
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
#define N 100003
typedef long long LL;
using namespace std;
template<const int maxn>struct Block
{
LL a[maxn],sum[maxn],tag[maxn];
int bs,cnt;
Block(){bs=sqrt(maxn),cnt=(maxn+bs-1)/bs;}
void build(LL *arr,int n)
{
memset(sum,0,sizeof(sum));
memset(tag,0,sizeof(tag));
FOR(i,1,n)
{
a[i]=arr[i];
sum[i/bs]+=a[i];
}
}
void push_down(int _)
{
if(!tag[_])return;
FOR(i,_*bs,(_+1)*bs-1)
a[i]+=tag[_];
tag[_]=0;
}
void update(int x,int y,int addval)
{
int kx=x/bs,ky=y/bs;
push_down(kx),push_down(ky);
if(kx==ky)
{
FOR(i,x,y)
{
a[i]+=addval;
sum[kx]+=addval;
}
return;
}
for(int i=x;i<(kx+1)*bs;i++)
{
a[i]+=addval;
sum[kx]+=addval;
}
for(int i=ky*bs;i<=y;i++)
{
a[i]+=addval;
sum[ky]+=addval;
}
FOR(i,kx+1,ky-1)
{
tag[i]+=addval;
sum[i]+=bs*addval;
}
}
LL query(int x,int y)
{
LL res=0;
int kx=x/bs,ky=y/bs;
push_down(kx),push_down(ky);
if(kx==ky)
{
FOR(i,x,y)res+=a[i];
return res;
}
for(int i=x;i<(kx+1)*bs;i++)
res+=a[i];
for(int i=ky*bs;i<=y;i++)
res+=a[i];
FOR(i,kx+1,ky-1)
res+=sum[i];
return res;
}
};
Block<N>B;
LL a[N];
int main()
{
int n,q;
scanf("%d%d",&n,&q);
FOR(i,1,n)scanf("%lld",&a[i]);
B.build(a,n);
FOR(i,1,q)
{
char c;int x,y;
LL z;
scanf(" %c",&c);
if(c=='Q')
{
scanf("%d%d",&x,&y);
printf("%lld\n",B.query(x,y));
}
else if(c=='C')
{
scanf("%d%d%d",&x,&y,&z);
B.update(x,y,z);
}
}
return 0;
}
线段树
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
#define N 100003
typedef long long LL;
using namespace std;
struct node
{
int L,R;
LL sum,tag;
void add(LL x)
{
tag+=x;
sum+=x*(R-L+1);
}
};
struct SegmentTree
{
node nd[N<<2];
void build(int k,int L,int R,int *arr)
{
nd[k].L=L,nd[k].R=R,nd[k].tag=0;
if(L==R)
{
nd[k].sum=arr[L];
return;
}
build(k<<1,L,L+R>>1,arr);
build(k<<1|1,(L+R>>1)+1,R,arr);
nd[k].sum=nd[k<<1].sum+nd[k<<1|1].sum;
return;
}
void push_down(int k)
{
if(!nd[k].tag)return;
nd[k<<1].add(nd[k].tag);
nd[k<<1|1].add(nd[k].tag);
nd[k].tag=0;
return;
}
void update(int k,int L,int R,LL addval)
{
if(L<=nd[k].L&&nd[k].R<=R)
{
nd[k].add(addval);
return;
}
push_down(k);
int mid=nd[k].L+nd[k].R>>1;
if(L<=mid)update(k<<1,L,R,addval);
if(mid<R)update(k<<1|1,L,R,addval);
nd[k].sum=nd[k<<1].sum+nd[k<<1|1].sum;
return;
}
LL query(int k,int L,int R)
{
if(L<=nd[k].L&&nd[k].R<=R)return nd[k].sum;
push_down(k);
int mid=nd[k].L+nd[k].R>>1;
LL res=0;
if(L<=mid)res+=query(k<<1,L,R);
if(mid<R)res+=query(k<<1|1,L,R);
return res;
}
}ST;
int a[N];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
FOR(i,1,n)scanf("%d",&a[i]);
ST.build(1,1,n,a);
char c;
FOR(i,1,m)
{
scanf(" %c",&c);
if(c=='Q')
{
int x,y;
scanf("%d%d",&x,&y);
printf("%lld\n",ST.query(1,x,y));
}
else if(c=='C')
{
int x,y;
LL z;
scanf("%d%d%lld",&x,&y,&z);
ST.update(1,x,y,z);
}
}
return 0;
}