POJ - 3468 A Simple Problem with Integers

刚开始学习线段树,再次以本题为例,做点笔记

题意:题目有两种操作,一种是询问[l,r]区间的和,另一种是[l,r]区间上的每一位数都加上C

分析:显然,直接将数字C加到区间上的每一位数上比较耗时,效率也比较低,所以我们要另辟蹊径,那就是lazy操作。

  lazy操作的意思就是先不将[l,r]区间的数上都加上C,也就是不直接将树的根的每一数+C,而是将+C这个标记推到他的两个子节点上,并将子节点更新sum[rt<<1]+=(tree[rt<<1].r-tree[rt<<1].l+1)*C(右节点同理),add[rt<<1]+=add[rt],add[rt]=0;这样做的话,只有这个区间被用到的时候,才会去用这个区间的子区间来更新他自己的区间和,大大的提高了效率

//pushdown
void pushdown(int rt){
	if(add[rt]){
		add[rt<<1]+=add[rt];
		add[rt<<1|1]+=add[rt];
		sum[rt<<1]+=1LL*(tree[rt<<1].r-tree[rt<<1].l+1)*add[rt];
		sum[rt<<1|1]+=1LL*(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*add[rt];
		add[rt]=0;
	}
}

  因为做了lazy操作,所以本个节点被使用时,才会被更新节点信息,所以在进行query时,必须使用pushdown函数,来下推标记

  下面是个人代码

#define debug
#include<stdio.h>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<functional>
#include<iomanip>
#include<map>
#include<set>
#define pb push_back
#define dbg(x) cout<<#x<<" = "<<(x)<<endl;
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll>PLL;
typedef pair<int,ll>Pil;
const ll INF = 0x3f3f3f3f;
const double inf=1e8+100;
const double eps=1e-8;
const int maxn =1e6;
const int N = 510;
const ll mod=1e9+7;
//------
//define
struct node{
	int l,r;
}tree[maxn<<2];
ll sum[maxn<<2],add[maxn<<2];
//pushup
void pushup(int rt) {
	sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 
}
//pushdown
void pushdown(int rt){
	if(add[rt]){
		add[rt<<1]+=add[rt];
		add[rt<<1|1]+=add[rt];
		sum[rt<<1]+=1LL*(tree[rt<<1].r-tree[rt<<1].l+1)*add[rt];
		sum[rt<<1|1]+=1LL*(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*add[rt];
		add[rt]=0;
	}
}
//buildtree
void build(int l,int r,int rt) {
	tree[rt].l=l;
	tree[rt].r=r;
	add[rt]=0;
	if(l==r) {
		//gra[rt]=a[l];
		scanf("%lld",&sum[rt]);
		return;
	}
	int m=l+r>>1;
	build(l,m,rt<<1);
	build(m+1,r,rt<<1|1);
	pushup(rt);
}
//update
void update(int L,int R,int C,int rt){
	if(tree[rt].l==L&&tree[rt].r==R){
		add[rt]+=C;
		sum[rt]+=1ll*C*(R-L+1);
		return;
	}
	if(tree[rt].l==tree[rt].r)return;
	pushdown(rt);
	int m=tree[rt].l+tree[rt].r>>1;
	if(R<=m){
		update(L,R,C,rt<<1);
	}else if(L>m){
		update(L,R,C,rt<<1|1);
	}else{
		update(L,m,C,rt<<1);
		update(m+1,R,C,rt<<1|1);
	}
	pushup(rt);
}
//query
ll query(int L,int R,int rt) {
	if(L==tree[rt].l&&R==tree[rt].r){
		return sum[rt];
	}
	pushdown(rt);
	ll ans=0;
	int m=tree[rt].l+tree[rt].r>>1;
	if(R<=m){
		ans+=query(L,R,rt<<1);
	}else if(L>m){
		ans+=query(L,R,rt<<1|1);
	}else{
		ans+=query(L,m,rt<<1);
		ans+=query(m+1,R,rt<<1|1);
	}
	return ans;
}
//solve
void solve() {
	int n,t;
	while(~scanf("%d%d",&n,&t)){
		build(1,n,1);
		while(t--){
			char mark[2];
			int A,B,C;
			scanf("%s",&mark);
			if(mark[0]=='Q'){
				scanf("%d%d",&A,&B);
				printf("%lld\n",query(A,B,1));
			}else{
				scanf("%d%d%d",&A,&B,&C);
				update(A,B,C,1);
			}
		}
	}
}
//main
int main() {
//	ios_base::sync_with_stdio(false);
#ifdef debug
	freopen("in.txt", "r", stdin);
//	freopen("out.txt","w",stdout);
#endif
//	cin.tie(0);
//	cout.tie(0);
	solve();
	/*
		#ifdef debug
			fclose(stdin);
			fclose(stdout);
			system("out.txt");
		#endif
	*/
	return 0;
}

  

posted @ 2018-04-27 22:04  visualVK  阅读(163)  评论(0编辑  收藏  举报