线段树之区间修改操作






例题洛谷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;
}






posted @ 2020-10-31 15:16  一个经常掉线的人  阅读(97)  评论(0编辑  收藏  举报