线段树之区间修改操作
例题洛谷P3372
算法应该没错但是就是超时了orz
#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include <typeinfo>
#define int long long
using namespace std;
const int MAXN=1e6+5;
int sum[MAXN<<2],add[MAXN<<2];
int N,M,k;
struct NODE{
int left;
int right;
int mid(){
return (left+right)>>1;
}
}node[MAXN<<2];
inline void PushUp(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
inline void PushDown(int rt,int m){
if(add[rt]){
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
sum[rt<<1]+=add[rt]*(m-(m>>1));
sum[rt<<1|1]+=add[rt]*(m>>1);
add[rt]=0;
}
}
inline void BuileTree(int rt,int l,int r){
node[rt].left=l;
node[rt].right=r;
add[rt]=0;
if(l==r){
scanf("%lld",&sum[rt]);
return ;
}
int m=node[rt].mid();
BuileTree(rt<<1,l,m);
BuileTree(rt<<1|1,m+1,r);
PushUp(rt);
}
inline void Update(int c,int l,int r,int rt){
if(l==node[rt].left&&r==node[rt].right){
add[rt]+=c;
sum[rt]+=c*(r-l+1);
return;
}
if(node[rt].left==node[rt].right) return;
PushDown(rt,node[rt].right-node[rt].left+1);
int m=node[rt].mid();
if(r<=m){
Update(c,l,r,rt<<1);
}
else if(l>m){
Update(c,l,r,rt<<1|1);
}
else {
Update(c,l,m,rt<<1);
Update(c,m+1,r,rt<<1|1);
}
PushUp(rt);
}
inline int Query(int l,int r,int rt){
if(node[rt].left==node[rt].right){
return sum[rt];
}
PushDown(rt,node[rt].right-node[rt].left+1);
int m=node[rt].mid();
int res=0;
if(r<=m) res+=Query(l,r,rt<<1);
else if(l>m) res+=Query(l,r,rt<<1|1);
else {
res+=Query(l,m,rt<<1);
res+=Query(m+1,r,rt<<1|1);
}
return res;
}
int a,b,c,d;
signed main(){
//freopen("testdata.in", "r", stdin);
scanf("%lld%lld",&N,&M);
BuileTree(1,1,N);
while(M--){
scanf("%lld",&a);
if(a==1){
scanf("%lld%lld%lld",&b,&c,&d);
Update(d,b,c,1);
}
else {
scanf("%lld%lld",&b,&c);
printf("%lld\n",Query(b,c,1));
}
}
return 0;
}
带注释版
#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include <typeinfo>
#define int long long
using namespace std;
const int MAXN=1e6+5;
int sum[MAXN<<2],add[MAXN<<2];
int N,M,k;
struct NODE{
int left;
int right;
int mid(){
return (left+right)>>1;
}
}node[MAXN<<2];
inline void PushUp(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
inline void PushDown(int rt,int m){
if(add[rt]){//核心操作,将标记往下传递
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
sum[rt<<1]+=add[rt]*(m-(m>>1));
sum[rt<<1|1]+=add[rt]*(m>>1);
add[rt]=0;
}
}
inline void BuileTree(int rt,int l,int r){
node[rt].left=l;
node[rt].right=r;
add[rt]=0;
if(l==r){
scanf("%lld",&sum[rt]);
return ;
}
int m=node[rt].mid();
BuileTree(rt<<1,l,m);
BuileTree(rt<<1|1,m+1,r);
PushUp(rt);
}
inline void Update(int c,int l,int r,int rt){
if(l==node[rt].left&&r==node[rt].right){
add[rt]+=c;
sum[rt]+=c*(r-l+1);
return;
}
if(node[rt].left==node[rt].right) return;
PushDown(rt,node[rt].right-node[rt].left+1);
int m=node[rt].mid();
if(r<=m){//包含在左区间
Update(c,l,r,rt<<1);
}
else if(l>m){//包含在右区间
Update(c,l,r,rt<<1|1);
}
else {
Update(c,l,m,rt<<1);
Update(c,m+1,r,rt<<1|1);
}
PushUp(rt);
}
inline int Query(int l,int r,int rt){
if(node[rt].left==node[rt].right){
return sum[rt];
}
PushDown(rt,node[rt].right-node[rt].left+1);
int m=node[rt].mid();
int res=0;
if(r<=m) res+=Query(l,r,rt<<1);//包含在左区间
else if(l>m) res+=Query(l,r,rt<<1|1);//包含在右区间
else {
res+=Query(l,m,rt<<1);
res+=Query(m+1,r,rt<<1|1);
}
return res;
}
int a,b,c,d;
signed main(){
//freopen("testdata.in", "r", stdin);
scanf("%lld%lld",&N,&M);
BuileTree(1,1,N);
while(M--){
scanf("%lld",&a);
if(a==1){
scanf("%lld%lld%lld",&b,&c,&d);
Update(d,b,c,1);
}
else {
scanf("%lld%lld",&b,&c);
printf("%lld\n",Query(b,c,1));
}
}
return 0;
}