士兵杀敌(一)
时间限制:
1000 ms | 内存限制:65535 KB
难度:
3
-
描述
-
南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的。
小工是南将军手下的军师,南将军现在想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧。
注意,南将军可能会问很多次问题。
-
输入
-
只有一组测试数据
第一行是两个整数N,M,其中N表示士兵的个数(1<N<1000000),M表示南将军询问的次数(1<M<100000)
随后的一行是N个整数,ai表示第i号士兵杀敌数目。(0<=ai<=100)
随后的M行每行有两个整数m,n,表示南将军想知道第m号到第n号士兵的总杀敌数(1<=m,n<=N)。
输出
-
对于每一个询问,输出总杀敌数
每个输出占一行
样例输入
-
5 2 1 2 3 4 5 1 3 2 4
样例输出
-
6 9
第一种解法
由 1,2,3,4,5可得1 3 6 10 15
1,3间总杀敌数 = a[3-1] = 6
2,4间总杀敌数 = a[4-1] - a[2-2] = 10 - 1 = 9;
# include<stdio.h> int a[1000000]; int main() { int n,m,i,x,y; scanf("%d %d",&n,&m); for(i=0;i<n;i++) { scanf("%d",&a[i]); } for(i=0;i<n-1;i++) { a[i+1] = a[i] + a[i+1]; } for(i=0;i<m;i++) { scanf("%d %d",&x,&y); if(x==1) printf("%d\n",a[y-1]); else printf("%d\n",a[y-1]-a[x-2]); } return 0; }
第二种解法:树状数组(特别适用于元素数据会改变)
树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值
#include<stdio.h> #include<string.h> int a[1000000]; int C[1000000]; void Update(int i,int value,int n) //A[i]的改变值为value { while(i<=n) { C[i]+=value; i+=i&(-i); } } int sum(int x) //求和 0到x { int ans=0; while(x>0) { ans+=a[x]; x-=x&(-x); } return ans; } int main() { int n,m; scanf("%d%d",&n,&m); int i,j,k; memset(a,0,sizeof(a)); for(i=1;i<=n;i++) //构建树状数组 { int num; scanf("%d",&num); j=i; while(j<=n) { a[j]=a[j]+num; j+=j&(-j); //结论 2^x=j&(-j) 编号j的二进制数 从右往左数连续有x个0 } } for(i=0;i<m;i++) { scanf("%d%d",&k,&j); int s1,s2; s1 = sum(k-1); s2 = sum(j); printf("%d",s2-s1);//两者相减即是[j,k]间元素和 putchar('\n'); } return 0; }
http://www.cnblogs.com/justforgl/archive/2012/07/27/2612364.html
void Update(int i,int value) //A[i]的改变值为value 从前往后修改 { while(i<=n) { C[i]+=value; i+=i&(-i); } }
void update(int star,int value) //从后往前
{
while(star>0)
{
add[star]+=value;
star-=lowbit(star);
}
}