士兵杀敌(四)
时间限制:2000 ms | 内存限制:65535 KB
难度:5
- 描述
-
南将军麾下有百万精兵,现已知共有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
1 /* 功能Function Description: NYOJ-123 士兵杀敌四------树桩数组--插线问点 2 开发环境Environment: DEV C++ 4.9.9.1 3 技术特点Technique: 4 版本Version: 5 作者Author: 可笑痴狂 6 日期Date: 20120807 7 备注Notes: 8 */ 9 10 // 代码一:----树状数组(插线问点) 11 #include<stdio.h> 12 #include<string.h> 13 int a[1000001]; 14 int M; 15 16 int lowbit(int i) 17 { 18 return i&(-i); 19 } 20 21 void update(int i,int num) 22 { 23 while(i<=M) 24 { 25 a[i]+=num; 26 i+=lowbit(i); 27 } 28 } 29 30 int getsum(int i) 31 { 32 int sum=0; 33 while(i>0) 34 { 35 sum+=a[i]; 36 i-=lowbit(i); 37 } 38 return sum; 39 } 40 41 int main() 42 { 43 int T,st,end,k,i; 44 char cmd[10]; 45 scanf("%d%d",&T,&M); 46 for(i=0;i<T;++i) 47 { 48 scanf("%s",cmd); 49 if(cmd[0]=='A') 50 { 51 scanf("%d%d%d",&st,&end,&k); 52 update(st,k); 53 update(end+1,-k); 54 } 55 else 56 { 57 scanf("%d",&k); 58 printf("%d\n",getsum(k)); //输出第k个人的军工 59 } 60 } 61 return 0; 62 }
1 //代码二: 2 //-----线段树(超时了----应该是代码写的大材小用了,本题只用查询一个点, 3 //自己写的插入函数可以把线段都更新了,适用于查询任意区间的军工总和,把查询函数稍加改进就能查线段了) 4 #include<stdio.h> 5 #include<malloc.h> 6 7 struct node 8 { 9 int lc,rc; 10 int sum; 11 }*tree; 12 13 void build(int s,int t,int T) 14 { 15 int mid=(s+t)>>1; 16 tree[T].lc=s; 17 tree[T].rc=t; 18 tree[T].sum=0; 19 if(s==t) 20 return ; 21 build(s,mid,T<<1); 22 build(mid+1,t,(T<<1)|1); 23 } 24 25 void insert(int s,int t,int add,int T) 26 { 27 if(tree[T].lc>t||tree[T].rc<s) 28 return ; 29 else if(s<tree[T].lc&&t<=tree[T].rc) 30 tree[T].sum+=add*(t-tree[T].lc+1); 31 else if(s>=tree[T].lc&&t<=tree[T].rc) 32 tree[T].sum+=add*(t-s+1); 33 else if(s>=tree[T].lc&&t>tree[T].rc) 34 tree[T].sum+=add*(tree[T].rc-s+1); 35 else 36 tree[T].sum+=add*(tree[T].rc-tree[T].lc+1); 37 if(tree[T].lc==tree[T].rc) 38 return ; 39 insert(s,t,add,T<<1); 40 insert(s,t,add,(T<<1)|1); 41 } 42 43 int qurry(int k,int T) 44 { 45 int mid=(tree[T].lc+tree[T].rc)>>1; 46 if(k<tree[T].lc||k>tree[T].rc) //不在此范围内直接跳出 47 return 0; 48 if(tree[T].lc==tree[T].rc) 49 return tree[T].sum; 50 if(k<=mid) 51 return qurry(k,T<<1); 52 else 53 return qurry(k,(T<<1)|1); 54 } 55 56 int main() 57 { 58 int T,st,end,k,i,M; 59 char cmd[10]; 60 scanf("%d%d",&T,&M); 61 tree=(struct node *)malloc(M*3*sizeof(struct node)); 62 build(1,M,1); 63 for(i=0;i<T;++i) 64 { 65 scanf("%s",cmd); 66 if(cmd[0]=='A') 67 { 68 scanf("%d%d%d",&st,&end,&k); 69 insert(st,end,k,1); 70 } 71 else 72 { 73 scanf("%d",&k); 74 printf("%d\n",qurry(k,1)); //输出第k个人的军工 75 } 76 } 77 return 0; 78 }