这题是要维护区间信息的线段树,且要进行区间修改。
模仿刘汝佳的算法竞赛入门经典中的线段树敲了一遍代码,结果提交上去虽然过了,但是耗时三千多毫秒。在网上借用别人的代码却发现只要一千八百多毫秒。检查了一遍,没找到在哪里和别人有差距。在提交榜上还看到有九百多毫秒就A了这题的,不知道差距在哪里。下次找到了再来更新
#include <iostream>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <stack>
#include <queue>
#include <list>
#include <set>
#include <map>
#include <climits>
/*
INT_MAX
LONG_MAX
LLONE_MIN
INT_MIN
ULLONG_MIN
*/
using namespace std;
typedef long long ll;
const ll MAXN=100000,MAXNODE=400010;
ll n,m;
ll sum[MAXNODE],addv[MAXNODE];
void maintain(ll o, ll L, ll R){
sum[o]=0;
if(R>L){
sum[o]+=sum[o<<1]+sum[o<<1|1];
}
sum[o]+=addv[o]*(R-L+1);
}
void update(ll o,ll L,ll R,const ll &y1, const ll &y2,const ll &v){
const ll lc=o<<1,rc=o<<1|1;
if(y1<=L&&y2>=R){
addv[o]+=v;
}else {
ll M=(L+R)/2;
if(y1<=M)update(lc,L,M,y1,y2,v);
if(y2>M)update(rc,M+1,R,y1,y2,v);
}
maintain(o,L,R);
}
ll ans;
void Qsum(ll o, ll L, ll R, ll add, const ll &y1, const ll &y2){
const ll lc=o<<1,rc=o<<1|1;
if(y1<=L&&y2>=R){
ans+=sum[o]+add*(R-L+1);
}else {
int M=(L+R)/2;
if(y1<=M)Qsum(lc,L, M,add+addv[o],y1,y2);
if(y2>M) Qsum(rc,M+1,R,add+addv[o],y1,y2);
}
}
int main()
{
scanf("%I64d%I64d",&n,&m);
for(int i=1;i<=n;i++){
ll k;
scanf("%I64d",&k);
update(1,1,n,i,i,k);
}
for(int i=1;i<=m;i++){
char c;
getchar();
scanf("%c",&c);
if(c=='Q'){
ll y1,y2;
ans=0;
scanf("%I64d%I64d",&y1,&y2);
Qsum(1,1,n,0,y1,y2);
printf("%I64d\n",ans);
}
else {
ll y1,y2,v;
scanf("%I64d%I64d%I64d",&y1,&y2,&v);
update(1,1,n,y1,y2,v);
}
}
return 0;
}