题目链接:https://www.luogu.com.cn/problem/P3372
几年没打线段树了,复习一下
#include<bits/stdc++.h>
using namespace std;
/*
线段树
定长数组的区间操作
时 : O(logn)
空 : O(nlogn)
*/
typedef long long val_type;
struct Node
{
int l,r,mid;
val_type sum,lazy;
/*
l,r : charge subscript start/end
sum : the sum of this sub-array
lazy : a tag for operate (eg. each elemt should add)
*/
};
vector<Node>node;
vector<val_type>a;
int n,k;
/*
parameter f down there is for locate the node on accessing
*/
val_type biuld(int l=1,int r=n,int f=1)
{
// printf("build( %d , %d , %d )\n",l,r,f);
if(l==r)
return (node[f]={
l,r,l,a[l]}).sum;
int mid=l+(r-l)/2;
return (node[f]={
l,r,mid,biuld(l,mid,f*2)+biuld(mid+1,r,f*2+1)}).sum;
}
val_type add(int&l,int&r,val_type&val,int f=1)
{
// printf("add( %d , %d , %d , %d )\n",l,r,val,f);
if(node[f].l>=l&&node[f].r<=r)
{
node[f].lazy+=val;
return val*(node[f].r-node[f].l+1);
}
val_type ret=0;
if(node[f].mid>=l)
ret+=add(l,r,val,f*2);
if(node[f].mid+1<=r)
ret+=add(l,r,val,f*2+1);
node[f].sum+=ret;
return ret;
}
val_type sum(int&l,int&r,int f=1)
{
if(node[f].lazy)
{
if(node[f].l!=node[f].r)
{
node[f*2].lazy+=node[f].lazy;
node[f*2+1].lazy+=node[f].lazy;
}
node[f].sum+=node[f].lazy*(node[f].r-node[f].l+1);
node[f].lazy=0;
}
if(node[f].l>=l&&node[f].r<=r)
return node[f].sum;
val_type ret=0;
if(node[f].mid>=l)
ret+=sum(l,r,f*2);
if(node[f].mid+1<=r)
ret+=sum(l,r,f*2+1);
return ret;
}
void check()
{
int cas=0;
for(auto it:node)
printf("%d : %d %d %lld %lld\n",cas++,it.l,it.r,it.sum,it.lazy);
}
int main()
{
int m;
scanf("%d%d",&n,&m);
a.resize(n+1);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
node.resize(log(n)/log(2)*n);
biuld();
// check();
val_type k;
for(int cas=1,op,l,r;cas<=m;cas++)
{
scanf("%d%d%d",&op,&l,&r);
if(op==1)
{
scanf("%lld",&k);
add(l,r,k);
}
else
{
printf("%lld\n",sum(l,r));
}
// check();
}
return 0;
}
/*
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
*/