POJ3468(线段树+lazy思想)

lazy 思想就是我这一段在更新的区间内这段更新一下记录一下增加的值到时候子线段要用的时候再用,这样可以节省时间,否则直接更新下去太暴力了会超时

#include
#include
using namespace std;
#define ls 2*i
#define rs 2*i+1
#define mid (l+r)/2
#define tmid (T[i].l+T[i].r)/2
const int mx = 1e5+5;
typedef long long int ll;
struct tree{
	int l,r;
	ll sum,add;
}T[4*mx];
ll a[mx];
ll creat(int i,int l,int r){
	T[i].l = l,T[i].r = r;
	T[i].add = 0;
	if(l == r)
		return T[i].sum = a[l];
	return	T[i].sum = creat(ls,l,mid)+creat(rs,mid+1,r);
}
void pushdown(int i){ //更新
	if(T[i].add){
		T[ls].add += T[i].add;
		T[rs].add += T[i].add;
		T[ls].sum += (T[ls].r-T[ls].l+1)*T[i].add;
		T[rs].sum += (T[rs].r-T[rs].l+1)*T[i].add;
		T[i].add = 0;
	}
}  
void update(int i,int l,int r,ll x){ 
	if(T[i].l >= l && T[i].r <= r){
		T[i].sum += (r-l+1)*x;
		T[i].add += x;
		return;
	}
	if(T[i].r < l || T[i].l > r)
		return ;
	if(T[i].l == T[i].r)
		 return;
	pushdown(i);  //子线段要用更新
	if(r <= tmid) update(ls,l,r,x);
	else if(l > tmid) update(rs,l,r,x);
	else{
		update(ls,l,tmid,x);
		update(rs,tmid+1,r,x);
	}
	T[i].sum = T[ls].sum+T[rs].sum;
}
ll query(int i,int l,int r){
	if(T[i].r < l || T[i].l > r)
		return 0;
	if(T[i].l >= l && T[i].r <= r)
		return T[i].sum;
	pushdown(i); //子线段要用更新一下
	return query(ls,l,r)+query(rs,l,r);
}
int n,q;
int main(){
	while(cin>>n>>q){
		for(int i = 1; i <= n; i++)
			cin>>a[i];
		creat(1,1,n);
		char c;
		int l,r;
		ll x;
		for(int i = 1; i <= q; i++){
			cin>>c;
			if(c == 'Q'){
				cin>>l>>r;
				cout<>l>>r>>x;
				update(1,l,r,x);
			}
		}
	}	
	return 0;
}

你可能感兴趣的:(线段树)