什么鬼鲁线段树然后模板错了~
就是给个标记。然后询问时再下发标记,节省时间
传送门
题目描述 Description
给你N个数,有两种操作:
1:给区间[a,b]的所有数增加X
2:询问区间[a,b]的数的和。
输入描述 Input Description
第一行一个正整数n,接下来n行n个整数,
再接下来一个正整数Q,每行表示操作的个数,
如果第一个数是1,后接3个正整数,
表示在区间[a,b]内每个数增加X,如果是2,
表示操作2询问区间[a,b]的和是多少。
pascal选手请不要使用readln读入
输出描述 Output Description
对于每个询问输出一行一个答案
样例输入 Sample Input
3
1
2
3
2
1 2 3 2
2 2 3
样例输出 Sample Output
9
数据范围
1<=n<=200000
1<=q<=200000
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree{
int l,r,lc,rc;
long long c,lazy;
}tr[510000];
int trlen,n,m,len;
long long a[210000];
void bt(int l,int r){
trlen++;int now=trlen;
tr[now].l=l;tr[now].r=r;
tr[now].c=0;tr[now].lazy=0;
tr[now].lc=tr[now].rc=-1;
if(l==r)tr[now].c=a[l];
else{
int mid=(l+r)/2;
tr[now].lc=trlen+1;bt(l,mid);
tr[now].rc=trlen+1;bt(mid+1,r);
tr[now].c=tr[tr[now].lc].c+tr[tr[now].rc].c;
}
}
void change(int now,int x,int y,long long c){
tr[now].c+=(y-x+1)*c;
if(tr[now].l==x&&tr[now].r==y){
tr[now].lazy+=c;return ;
}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(y<=mid)change(lc,x,y,c);
else if(x>=mid+1)change(rc,x,y,c);
else{
change(lc,x,mid,c);
change(rc,mid+1,y,c);
}
}
long long findsum(int now,int l,int r){
if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(tr[now].lazy!=0){
tr[lc].c+=tr[now].lazy*(tr[lc].r-tr[lc].l+1);
tr[rc].c+=tr[now].lazy*(tr[rc].r-tr[rc].l+1);
tr[lc].lazy+=tr[now].lazy;
tr[rc].lazy+=tr[now].lazy;
tr[now].lazy=0;
}
if(l>=mid+1)return findsum(rc,l,r);
else if(r<=mid)return findsum(lc,l,r);
else return findsum(lc,l,mid)+findsum(rc,mid+1,r);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
trlen=0;bt(1,n);
scanf("%d",&m);
int s,x,y;long long z;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&s,&x,&y);
if(s==1){
scanf("%lld",&z);
change(1,x,y,z);
}
else{
printf("%lld\n",findsum(1,x,y));
}
}
}