程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> poj 3468 A Simple Problem with Integers(線段樹 成段增減+區間求和)

poj 3468 A Simple Problem with Integers(線段樹 成段增減+區間求和)

編輯:C++入門知識

 

題意:有n個數和兩種操作,C A B C和 Q AB,“C A B C”表示區間A~B的數均增加C, Q AB表示詢問區間A~B的和。

 

思路:

是典型的線段樹成段更新和區間求和問題。不過我被書上誤導了,導致調試了一下午,最後搞得特暈。所以,還是要相信自己的想法,不要完全依賴別人的。。。

區間線段更新時,有向上更新(父節點)和向下更新(子節點)。一定要理解好它。當對某一區間更新時,比如更新

[1,3],同時它的父節點[1,5]也要更新。向下更新即當前區間不能被要更新區間完全覆蓋,那麼就要把當前區間的公共增量向左右子樹傳遞,並把當前區間的增量改為0,同時左右子樹的sum值也要改變,add的改變和sum的改變的同步的。

 

 

#include 
#include 
#define LL long long

const int maxn = 100005;
__int64 a[maxn];

struct line
{
	int l;
	int r;
	LL sum,add;//增加兩個區域,一個記錄區間之和,一個記錄區間公共增量
}tree[maxn<<2];

void build(int v, int l, int r)
{
	tree[v].l = l;
	tree[v].r = r;
	tree[v].add = 0;
	if(l == r)
	{
		tree[v].sum = a[r];
		return;
	}

	int mid = (l+r)>>1;
	build(v*2,l,mid);
	build(v*2+1,mid+1,r);
	tree[v].sum = tree[v*2].sum + tree[v*2+1].sum;

}

void update(int v, int l, int r,__int64 add)	//更新區間l~r分別加上add;
{
	tree[v].sum += (r-l+1)*add;//不論該區間是否是要更新區間,肯定是當前區間的子區間,所以也要更新當前區間sum值。
	
	if(tree[v].l == l && tree[v].r == r)//如果當前區間恰好被要更新區間完全覆蓋,那麼用add維護當前區間公共增量,不必往下更新了。
	{
		tree[v].add += add;		//注意是 +=,因為節點本身也有增量
		return;
	}

	int mid = (tree[v].l + tree[v].r)>>1;

	if(tree[v].add)	//如果上面沒有走掉,就把增量向下傳遞,注意傳遞增量的同時左右子樹的sum值也要改變
	{
		tree[v*2].add += tree[v].add;
		tree[v*2+1].add += tree[v].add;
		tree[v*2].sum += tree[v].add * (tree[v*2].r-tree[v*2].l+1);
		tree[v*2+1].sum += tree[v].add * (tree[v*2+1].r-tree[v*2+1].l+1);
		tree[v].add = 0;
	}

	if(r <= mid)
		update(v*2,l,r,add);
	else
	{
		if(l > mid)
			update(v*2+1,l,r,add);
		else
		{
			update(v*2,l,mid,add);
			update(v*2+1,mid+1,r,add);
		}
	}
	
}

__int64 query(int v, int l, int r)
{
	if(tree[v].l == l && tree[v].r == r)
		return tree[v].sum;

	int mid = (tree[v].l + tree[v].r)>>1;

	if(tree[v].add)//上面沒走掉,同樣增量向下傳遞,子樹的sum值也在改變。
	{
		tree[v*2].add += tree[v].add;
		tree[v*2+1].add += tree[v].add;
		tree[v*2].sum += tree[v].add * (tree[v*2].r-tree[v*2].l+1);
		tree[v*2+1].sum += tree[v].add * (tree[v*2+1].r-tree[v*2+1].l+1);
		tree[v].add = 0;
	}

	if(r <= mid)
		query(v*2,l,r);
	else
	{
		if(l > mid)
			return query(v*2+1,l,r);
		else
			return query(v*2,l,mid)+ query(v*2+1,mid+1,r);
	}
}

int main()
{
	int n,m;
	char ch[2];
	int l,r;
	__int64 ans,add;
	scanf(%d %d,&n,&m);
	for(int i = 1; i <= n; i++)
		scanf(%I64d,&a[i]);

	build(1,1,n);

	while(m--)
	{
		scanf(%s,ch);
		if(ch[0] == 'C')
		{
			scanf(%d %d %I64d,&l,&r,&add);
			update(1,l,r,add);
		}

		else
		{
			scanf(%d %d,&l,&r);
			ans = query(1,l,r);
			printf(%I64d
,ans);
		}
	}
	return 0;
}


 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved