题目链接:https://vjudge.net/contest/347398#problem/A
翻译:
输入两个数n和q
接下来n个数,m种操作
Q a b:求[a,b]的区间和
C a b c:区间[a,b]内的每个数加c
分析:
线段树很容易维护。
关键是用树状数组如何维护
运用树状数组必须引进差分数组。
核心代码:
for(int i=1; i<=n; i++)
{
scanf("%lld",&m);
a[i]=a[i-1]+m-tab;/*求差分数组cha[i]的前缀和*/
//m-tab相当于cha[i]=a[i]-a[i-1]
b[i]=b[i-1]+(m-tab)*i;/*求cha[i]*i的前缀和*/
c[i]=a[i]-a[i-lowbit(i)];/*用树状数组分别维护cha[i]和cha[i]*i*/
d[i]=b[i]-b[i-lowbit(i)];
tab=m;
}
完整代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+10;
LL a[N],b[N],c[N],d[N];
int n;
int lowbit(int x)
{
return x&(-x);
}
LL sum(int x)
{
LL tot=0;
int mul=x;
while(x)
{
tot+=(mul+1)*c[x];
tot-=d[x];
x-=lowbit(x);
}
return tot;
}
void update(int x,int num)
{
int mul=x;
while(x<=n)
{
c[x]+=num;
d[x]+=num*mul;
x+=lowbit(x);
}
}
int main()
{
int q;
char ch[2];
scanf("%d%d",&n,&q);
LL m,tab=0;
for(int i=1; i<=n; i++)
{
scanf("%lld",&m);
a[i]=a[i-1]+m-tab;/*求差分数组cha[i]的前缀和*/
b[i]=b[i-1]+(m-tab)*i;/*求cha[i]*i的前缀和*/
c[i]=a[i]-a[i-lowbit(i)];
d[i]=b[i]-b[i-lowbit(i)];
tab=m;
}
while(q--)
{
scanf("%s",ch);
if(ch[0]=='Q')
{
int x,y;
scanf("%d%d",&x,&y);
printf("%lld\n",sum(y)-sum(x-1));
}
if(ch[0]=='C')
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
update(x,z);
update(y+1,-z);
}
}
return 0;
}
你只需要静心思考一下即可