士兵杀敌(二)
时间限制:
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 <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX=1e6+10; char str[10]; struct Node { int l; int r; int sum; }tree[MAX*4]; int Push(int o) { tree[o].sum = tree[o*2].sum + tree[o*2+1].sum; } void BuildTree(int o, int l , int r) { tree[o].l = l; tree[o].r = r; if( l == r) { int t; scanf("%d",&t); tree[o].sum = t; return ; } int mid = (l + r )/2; BuildTree(o*2 , l , mid); BuildTree(o*2+1 , mid+1 , r); Push(o); } int TreeSum(int o , int l , int r ,int x ,int y) { if( l == x && r == y) { return tree[o].sum; } int mid = (l + r) / 2; if( mid < x) //右边 return TreeSum(o*2+1 , mid+1 , r , x , y); else if( y <= mid) return TreeSum(o*2 , l ,mid , x , y); else return TreeSum(o*2 , l , mid , x , mid ) + TreeSum(o*2+1 , mid+1 , r , mid+1 , y); } void Update(int o , int l , int r , int x, int y) { if( l == r ) { tree[o].sum += y; return ; } int mid = (l + r) / 2; if( x <= mid ) //找左子树 Update(o*2 , l , mid , x , y); else //找右子树 Update(o*2+1 , mid+1 , r ,x , y); Push(o); //更新当前节点 } int main() { int n , m; scanf("%d %d",&n,&m); int x, y; BuildTree(1, 1 , n); for(int i = 0; i < m; i++) { scanf("%s",str); if(str[0] == 'Q') { scanf("%d %d",&x,&y); printf("%d\n",TreeSum(1,1,n,x,y)); } if(str[0] == 'A') { scanf("%d %d",&x,&y); Update(1,1,n,x,y); } } return 0; }
-
只有一组测试数据