【線段樹】SSLOJ 2648 線段樹練習五

LinkLink

SSLOJSSLOJ 26482648

DescriptionDescription

一行N個方格,開始每個格子裏的數都是0。現在動態地提出一些問題和修改:提問的形式是求某一個特定的子區間[a,b]中所有元素的和;修改的規則是指定某一個格子x,加上或者減去一個特定的值A。現在要求你能對每個提問作出正確的回答。1≤N≤100000,提問和修改的總數可能達到100000條。

InputInput

20
6 
M 1 1 
M 2 2 
M 3 4 
M 3 -5 
M 6 7 
C	 2 6

OutputOutput

8

TrainTrain ofof ThoughtThought

直接線段樹的區間計數模板就好了
定義一個線段樹,裏面再定個參數vol,用於統計覆蓋當前區間的線段數

CodeCode

#include<iostream>
#include<cstdio>

using namespace std;

struct Tree
{
	int l, r, vol;
}tree[500000];

void Build(int x, int L, int R)
{
	tree[x].l = L; tree[x].r = R;
	int mid = (L + R) >> 1;
	if (tree[x].l == tree[x].r) return ;
	Build (x * 2, L, mid);
	Build (x * 2 + 1, mid + 1, R);//這裏要注意,和前面的不一樣,mid要+1,因爲是格子,不是點
}//建樹

void Ins(int x, int pla, int num)
{
	if (tree[x].l == pla && tree[x].r == pla) { 
	    tree[x].vol += num;
		return ;
	}
	if (pla <= tree[x * 2].r) Ins(x * 2, pla, num);
	 else Ins(x * 2 + 1, pla, num);
	tree[x].vol = tree[x * 2].vol + tree[x * 2 + 1].vol;//通過左右兒子的值,算出父親節點的值(因爲左右兒子的值之和爲父親的值,而下面改變了,直接將上面的值覆蓋掉就好了)
}

int Count(int x, int L, int R)
{
	if (tree[x].l == L && tree[x].r == R)
		return tree[x].vol;
	if (R <= tree[x * 2].r) return Count (x * 2, L, R);
	 else if (L >= tree[x * 2 + 1].l) return Count (x * 2 + 1, L, R);		 
	  else 
	  return Count(x * 2, L, tree[x * 2].r) + Count(x * 2 + 1, tree[x * 2 + 1].l, R);
} 

int main()
{
	char c;
	int n, m, x, y;
	scanf("%d", &n);
	scanf("%d", &m);
	Build(1, 1, n);
	getchar(); 
	for (int i = 1; i <= m; ++i)
	{
		c = getchar();
		if (c == 'M') {
			scanf("%d%d", &x, &y);
			getchar();
			Ins(1, x, y);
		}
		 else {
		 	scanf("%d%d", &x, &y);
			getchar();
			printf("%d\n", Count(1, x, y));
		 } 
	}
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章