POJ——3468(线段树区间修改模板题)Simple Problem with Integers

原题链接:http://poj.org/problem?id=3468

题意:给你一个编号从1到N的整数序列,会进行若干个区间修改和查询功能,请你输出每次查询后的结果。

解题思路:这是一道线段树区间修改的模板题,我们理解好题意照做即可,要注意范围,利用long long来存储。

AC代码:

#include

#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define fi first
#define se second
#define mp make_pair
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5+5;//最大值。
//****************分割线,以上为自定义代码模板*****************//


struct node{
	int l,r;//左右端点。
	ll sum,lazy;//区间和和lazy标记。
}SegTree[maxn<<2];
void BuildTree(int rt,int l,int r){
	SegTree[rt].l=l;SegTree[rt].r=r;
	SegTree[rt].lazy=0;
	if(l==r){
		cin>>SegTree[rt].sum;
		return;
	}
	BuildTree(rt<<1,l,(l+r)>>1);
	BuildTree(rt<<1|1,((l+r)>>1)+1,r);
	SegTree[rt].sum=SegTree[rt<<1].sum+SegTree[rt<<1|1].sum;
}
void PushDown(int rt){
	if(SegTree[rt].lazy){
		SegTree[rt<<1].lazy+=SegTree[rt].lazy;
		SegTree[rt<<1|1].lazy+=SegTree[rt].lazy;
		SegTree[rt<<1].sum+=(SegTree[rt<<1].r-SegTree[rt<<1].l+1)*SegTree[rt].lazy;
		SegTree[rt<<1|1].sum+=(SegTree[rt<<1|1].r-SegTree[rt<<1|1].l+1)*SegTree[rt].lazy;
		SegTree[rt].lazy=0;
	}
}
void UpDate(int rt,int c,int l,int r){
	if(SegTree[rt].l==l&&SegTree[rt].r==r){
		SegTree[rt].sum+=(SegTree[rt].r-SegTree[rt].l+1)*c;
		SegTree[rt].lazy+=c;
		return;
	}
	PushDown(rt);
	int mid=(SegTree[rt].l+SegTree[rt].r)>>1;
	if(r<=mid){
		UpDate(rt<<1,c,l,r);//全部在左子树。
	}
	else if(l>mid){
		UpDate(rt<<1|1,c,l,r);//全部在右子树。
	}
	else{
		UpDate(rt<<1,c,l,mid);
		UpDate(rt<<1|1,c,mid+1,r);
	}
	SegTree[rt].sum=SegTree[rt<<1].sum+SegTree[rt<<1|1].sum;
}
ll QueryTree(int rt,int l,int r){
	if(SegTree[rt].l==l&&SegTree[rt].r==r){
		return SegTree[rt].sum;
	}
	PushDown(rt);
	int mid=(SegTree[rt].l+SegTree[rt].r)>>1;
	ll ans=0;
	if(r<=mid){
		ans+=QueryTree(rt<<1,l,r);//全部在左子树。
	}
	else if(l>mid){
		//全部在右子树。
		ans+=QueryTree(rt<<1|1,l,r);
	}
	else{
		ans+=QueryTree(rt<<1,l,mid);
		ans+=QueryTree(rt<<1|1,mid+1,r);
	}
	return ans;
}
int main(){
	//freopen("in.txt", "r", stdin);//提交的时候要注释掉
	IOS;
	int n,q;
	while(cin>>n>>q){
		BuildTree(1,1,n);
		string op;
		int a,b,c;
		while(q--){
			cin>>op;
			if(op=="Q"){
				cin>>a>>b;
				cout<<QueryTree(1,a,b)<<endl;
			}
			else{
				cin>>a>>b>>c;
				UpDate(1,c,a,b);
			}
		}
	}
	return 0;
}

你可能感兴趣的:(线段树专题,算法,线段树,区间修改)