poj3468 A Simple Problem with Integers

        题意:n个数,你可以给一个区间加上c,或者询问一个区间的和。

        思路:线段树(成段更新)。简直模版得不能再模板。。不过我还是因为不熟练写了好些bug。


#include <iostream>    
#include <stdio.h>    
#include <cmath>    
#include <algorithm>    
#include <iomanip>    
#include <cstdlib>    
#include <string>     
#include <vector>    
#include <queue>    
#include <stack>    
#include <map>  
#include <set>  
#include <ctype.h>    
#define ll long long

using namespace std;  

struct node{
	int l,r;
	ll val;
	ll add;
};
node tree[400010];

ll num[100010];

ll build_tree(int n,int l,int r){
	tree[n].l=l; tree[n].r=r; tree[n].add=0;
	if(l==r){
		tree[n].val=num[l];
		return num[l];
	}
	int mid=(l+r)/2;
	tree[n].val=build_tree(n*2,l,mid)+build_tree(n*2+1,mid+1,r);
	return tree[n].val;
}

void update(int n,int l,int r,ll v){
	tree[n].val+=(r-l+1)*v;
	if(tree[n].l==l&&tree[n].r==r){	
		if(l!=r)tree[n].add+=v;
		return;
	}
	int mid=(tree[n].l+tree[n].r)/2;
	if(tree[n].add){
		update(n*2,tree[n].l,mid,tree[n].add);
		update(n*2+1,mid+1,tree[n].r,tree[n].add);
		tree[n].add=0;
	}
	if(r<=mid){
		update(n*2,l,r,v);
	}else{
		if(l<=mid){
			update(n*2,l,mid,v);
			update(n*2+1,mid+1,r,v);
		}else{
			update(n*2+1,l,r,v);
		}
	}
}

ll query(int n,int l,int r){
	if(tree[n].l==l&&tree[n].r==r){
		return tree[n].val;
	}
	int mid=(tree[n].l+tree[n].r)/2;
	if(tree[n].add){
		update(n*2,tree[n].l,mid,tree[n].add);
		update(n*2+1,mid+1,tree[n].r,tree[n].add);
		tree[n].add=0;
	}
	//
	if(r<=mid){
		return query(n*2,l,r);
	}else{
		if(l<=mid){
			return query(n*2,l,mid)+query(n*2+1,mid+1,r);
		}else{
			return query(n*2+1,l,r);
		}
	}
}

int main(){
	int n,q;
	while(cin>>n>>q){
		for(int i=1;i<=n;i++){
			scanf("%lld",&num[i]);
		}
		build_tree(1,1,n);
		
		while(q--){
			char str[10];
			scanf("%s",str);
			if(str[0]=='C'){
				int a,b,c;
				scanf("%d%d%d",&a,&b,&c);
				update(1,a,b,c);
			}else{
				int a,b;
				scanf("%d%d",&a,&b);
				ll ans=query(1,a,b);
				printf("%lld\n",ans);
			}
		}
	}
	return 0;
} 


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