版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/83008240
题目:poj3468.
题目大意:给定一个序列a,要求支持:
1.格式C a b c,表示将[a,b]的权值都加上c.
2.格式Q a b,表示查询[a,b]的权值和.
线段树裸题(我像个傻子一样写了个LCT做了一遍),可是我们这里不用线段树,我们讨论树状数组的解法.
我们已经知道树状数组支持单点修改区间查询和区间修改单点查询,那么可不可以让树状数组支持区间修改区间查询呢?
我们现在继续将思路留在差分数组上,我们设A是a的差分数组,那么A[1,n]的和就是.
我们发现这个东西用一个树状数组还是不好维护,我们可以在变式.
我们发现这个东西貌似就可以用两个树状数组维护,我们可以用一个树状数组维护A[i],再用一个树状数组维护A[i]*(i-1).
代码如下:
//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=100000;
LL c[N+9][2],a[N+9];
int n,q;
int lowbit(int x){return x&-x;}
void add(int x,LL num,int t){
while (x<=n){
c[x][t]+=num;
x+=lowbit(x);
}
}
LL query(int x,int t){
LL sum=0;
while (x){
sum+=c[x][t];
x-=lowbit(x);
}
return sum;
}
char rc(){
char c=getchar();
while (c<'A'||c>'Z') c=getchar();
return c;
}
Abigail into(){
scanf("%d%d",&n,&q);
for (int i=1;i<=n;i++)
scanf("%lld",&a[i]);
}
Abigail work(){
for (int i=n;i>=1;i--)
a[i]-=a[i-1];
for (int i=1;i<=n;i++)
add(i,a[i],0),add(i,a[i]*(i-1),1);
}
Abigail getans(){
char opt;
int l,r;
LL d;
for (int i=1;i<=q;i++){
opt=rc();
if (opt=='C'){
scanf("%d%d%lld",&l,&r,&d);
add(l,d,0);add(r+1,-d,0);
add(l,d*(l-1),1);add(r+1,-d*r,1);
}else{
scanf("%d%d",&l,&r);
printf("%lld\n",query(r,0)*r-query(r,1)-query(l-1,0)*(l-1)+query(l-1,1));
}
}
}
int main(){
into();
work();
getans();
return 0;
}