标签:style blog http io ar color os 使用 sp
南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的。
小工是南将军手下的军师,南将军经常想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧。
南将军的某次询问之后士兵i可能又杀敌q人,之后南将军再询问的时候,需要考虑到新增的杀敌数。
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
对于很小的n用一般的for循环可以求和或变更内容后求和得出题目的答案,可是对于很大的n来说,程序会因为多次循环而变的很慢(时间就是金钱啊,有木有),所以我们要想法优化数据的存储结构,一个好的数据结构带来的肯定是时间上的减缩,何乐而不为.废话不多说,本题使用树状数组来存储题目数据。首先看图片(来自百度)认识一下树状数组:
我们称数组c为树状数组,它的特点是,c[i]存储的是A[i-2^k + 1]到A[i]的和(和士兵杀敌(一)的数组有的类似,这里的数组c[i]存储的是某一个区间的和),需要说明的是:k为i在二进制形式下有效0的个数(一般用 i & (-i) 直接求出 2^k的值).
那么问题来了.....
1. 如何求出前 i 项的和(求前 i 项和为了的到某一区间的和,这个思想用于士兵杀敌(一)中)。
2. 若数组A[]的某一个元素更新,如何更新数组c[]的值。
对于这两个问题请参考:http://www.java3z.com/cwbwebhome/article/article19/zip/treearray.zip实在不是太懂,汗颜啊!
下面给出代码:
#include<stdio.h> #define MAX 1000000 int ans[MAX+1]; /*直接计算2^k的值*/ int lowbit(int x) { return x&(-x); } /*更新数组位置 i 的值*/ void update(int i,int n,int N) { while(i<=N){ //printf("i = %d\n",i); ans[i]+=n; i+=lowbit(i); } } /*求出前 i 项的和*/ int sum(int n) { int s=0; while(n>0){ s+=ans[n]; n-=lowbit(n); } return s; } int main() { int N,M; int i,t,p,q; char ch[6]; scanf("%d%d",&N,&M); for(i=1;i<=N;i++){ scanf("%d",&t); update(i,t,N); } for(i=1;i<=M;i++){ scanf("%s %d %d",ch,&p,&q); if(ch[0]=='Q') printf("%d\n",sum(q)-sum(p-1)); else update(p,q,N); } return 0; }
标签:style blog http io ar color os 使用 sp
原文地址:http://blog.csdn.net/u012437355/article/details/41483599