1. 程式人生 > >nyoj 123 士兵殺敵(四)

nyoj 123 士兵殺敵(四)

描述

南將軍麾下有百萬精兵,現已知共有M個士兵,編號為1~M,每次有任務的時候,總會有一批編號連在一起人請戰(編號相近的人經常在一塊,相互之間比較熟悉),最終他們獲得的軍功,也將會平分到每個人身上,這樣,有時候,計算他們中的哪一個人到底有多少軍功就是一個比較困難的事情,軍師小工的任務就是在南將軍詢問他某個人的軍功的時候,快速的報出此人的軍功,請你編寫一個程式來幫助小工吧。

假設起始時所有人的軍功都是0.

輸入
只有一組測試資料。
每一行是兩個整數T和M表示共有T條指令,M個士兵。(1<=T,M<=1000000)
隨後的T行,每行是一個指令。
指令分為兩種:
一種形如
ADD 100 500 55 表示,第100個人到第500個人請戰,最終每人平均獲得了55軍功,每次每人獲得的軍功數不會超過100,不會低於-100。
第二種形如:
QUERY 300 表示南將軍在詢問第300個人的軍功是多少。
輸出
對於每次查詢輸出此人的軍功,每個查詢的輸出佔一行。
樣例輸入
4 10
ADD 1 3 10
QUERY 3
ADD 2 6 50
QUERY 3
樣例輸出
10

60

樹狀陣列的區間更新演算法.

 
#include <cstdio>
using namespace std;
#define max_n 1000300
int n;
int m[max_n];
int lowbit(int i)
{
	return i&(-i);
}
void update(int i, int num)
{
	while (i <= n)
	{
		m[i] += num;
		i += lowbit(i);
	}
}
int sum(int i)
{
	int nsum = 0;
	while (i > 0)
	{
		nsum += m[i];
		i -= lowbit(i);
	}
	return nsum;
}
int main()
{
	int t;
	int i;
	int num, b, e;
	char s[10];
	scanf("%d%d", &t, &n);
	while (t--)
	{
		scanf("%s", s);
		if (s[0] == 'A')
		{
			scanf("%d%d%d", &b, &e, &num);
			update(b, num);
			update(e + 1, -num);
		}
		else
		{
			scanf("%d",&i);
			printf("%d\n",sum(i));
		}
	}
}