NYOJ题目116 士兵杀敌(二)

 

士兵杀敌(二)

时间限制:1000 ms  |  内存限制:65535 KB

难度:5

描述

南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的。

小工是南将军手下的军师,南将军经常想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧。

南将军的某次询问之后士兵i可能又杀敌q人,之后南将军再询问的时候,需要考虑到新增的杀敌数。

输入
只有一组测试数据
第一行是两个整数N,M,其中N表示士兵的个数(1<N<1000000),M表示指令的条数。(1<M<100000)
随后的一行是N个整数,ai表示第i号士兵杀敌数目。(0<=ai<=100)
随后的M行每行是一条指令,这条指令包含了一个字符串和两个整数,首先是一个字符串,如果是字符串QUERY则表示南将军进行了查询操作,后面的两个整数m,n,表示查询的起始与终止士兵编号;如果是字符串ADD则后面跟的两个整数I,A(1<=I<=N,1<=A<=100),表示第I个士兵新增杀敌数为A.
输出
对于每次查询,输出一个整数R表示第m号士兵到第n号士兵的总杀敌数,每组输出占一行
样例输入
5 6
1 2 3 4 5
QUERY 1 3
ADD 1 2
QUERY 1 3
ADD 2 3
QUERY 1 2
QUERY 1 5
样例输出
6
8
8
20

利用树状数组来存放士兵杀敌数

 

 

#include <stdio.h>
int a[1000000],Tree_a[1000000];//a[]为原始数据组,Tree_a[]树状数组
int lowbit(int i)
{  // 返回i因子中含有 2的最大幂,如6的因子中最大2的幂是2^1 = 2 ,8的因子最大2次幂 2^3 = 8;
	return i&(-i);
}
void change(int x, int y,int n)
{
	while(x<=n)
	{
		Tree_a[x] += y;
		x += lowbit(x);
	}
}
int f_sum(int x)
{//返回前x个数的和
	if(x==0) return 0;
	int sum = 0;
	while( x>0 )
	{
		sum += Tree_a[x]; //求前x数的和
		x -= lowbit(x);
	}
	return sum;
}
int main()
{
	int m,n,i,e,j,x,y;
	char str[6];
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&e);
		a[i] = e;
		if(i&1)//奇数,树状数组与原始位置数据一样
			Tree_a[i] = a[i];
		else //偶数,树状数组对应位置存的为几项的和
		{
			int sum = 0;
			for(j=i+1-lowbit(i);j<=i;j++)	sum += a[j];
			Tree_a[i] = sum;
		}
	}

	while(m--)
	{
		scanf("%s%d%d",str,&x,&y);
		if(str[0]=='Q')	 printf("%d\n",f_sum(y) - f_sum(x-1));
		else 	change(x,y,n);// 第x个位置增加 y,调整x到N之间的和的值
	}
}