【poj】A Simple Problem with Integers-(区间加减,查询区间总和)。
A Simple Problem with Integers
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 71967 | Accepted: 22196 | |
Case Time Limit: 2000MS |
Description
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000. The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000. Each of the next Q lines represents an operation. "C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000. "Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
4 55 9 15
Hint
The sums may exceed the range of 32-bit integers.
Source
POJ Monthly--2007.11.25, Yang Yi
题目大意:对一段区间的全部数进行加减(区间加减),或者查询区间总和;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 using namespace std; 6 typedef long long LL; 7 typedef struct Line 8 { 9 LL Left,Right; 10 LL Key;/*关键值*/ 11 LL Times;/*计数器*/ 12 LL Count; 13 }LR; 14 LR ID[100860];/*每一个节点都需要一个存储*/ 15 LL Key_SUM; 16 LL UP_Key(LL n) 17 { 18 return ID[n*2].Key+ID[n*2+1].Key; 19 } 20 LL UP_Count(LL n) 21 { 22 return ID[n*2].Count+ID[n*2+1].Count; 23 } 24 void Build(LL L,LL R,LL n) /*输入时建立二叉树根*/ 25 { 26 LL Mid=(L+R)/2; 27 ID[n].Left=L;ID[n].Right=R; 28 ID[n].Key=0;ID[n].Times=0;/*初始化为0*/ 29 if (L==R)/*找到根节点的时候结束*/ 30 { 31 scanf("%I64d",&ID[n].Key); 32 ID[n].Count=1;return; 33 } 34 Build(L,Mid,2*n);Build(Mid+1,R,2*n+1); 35 ID[n].Key=UP_Key(n);ID[n].Count=UP_Count(n); 36 } 37 38 void Search(LL L,LL R,LL Step)/*求区间和*/ 39 { 40 if(L==ID[Step].Left && R==ID[Step].Right) 41 { 42 Key_SUM+=ID[Step].Key+ID[Step].Times*(R-L+1); 43 return ; 44 } 45 if(ID[Step].Times!=0) 46 { 47 ID[Step*2].Times+=ID[Step].Times; 48 ID[Step*2+1].Times+=ID[Step].Times; 49 ID[Step].Key+=(ID[Step].Right-ID[Step].Left+1)*ID[Step].Times; 50 ID[Step].Times=0; 51 } 52 LL Mid=(ID[Step].Left+ID[Step].Right)/2; 53 if (Mid>=R)Search(L,R,Step*2); 54 else if (Mid<L)Search(L,R,Step*2+1); 55 else 56 { 57 Search(L,Mid,Step*2); 58 Search(Mid+1,R,Step*2+1); 59 } 60 } 61 void UpData(LL L,LL R,LL Step,LL num)/*区域更新*/ 62 { 63 if(L==ID[Step].Left && R==ID[Step].Right) 64 {ID[Step].Times+=num;return;} 65 ID[Step].Key+=num*(R-L+1); 66 LL Mid=(ID[Step].Left+ID[Step].Right)/2; 67 if (Mid>=R) UpData(L,R,Step*2,num); 68 else if (Mid<L) UpData(L,R,Step*2+1,num); 69 else 70 { 71 UpData(L,Mid,Step*2,num); 72 UpData(Mid+1,R,Step*2+1,num); 73 } 74 } 75 76 int main() 77 { 78 LL N,i,a,b,c,q; 79 while(scanf("%I64d%I64d",&N,&q)!=EOF) 80 { 81 Build(1,N,1); 82 char Str; 83 while(q--) 84 { 85 scanf(" %c",&Str); 86 if(Str=='Q') 87 { 88 scanf("%I64d%I64d",&a,&b); 89 Key_SUM=0;Search(a,b,1); 90 printf("%I64d\n",Key_SUM); 91 } 92 else 93 { 94 scanf("%I64d%I64d%I64d",&a,&b,&c); 95 UpData(a,b,1,c); 96 } 97 } 98 } 99 return 0; 100 }
更新模板:(2016.4.14)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #define MaxN 1008600 6 using namespace std; 7 typedef long long LL; 8 LL Len; 9 struct Node{LL L,R,Key,Add;}ID[MaxN];/*每一个节点都需要一个存储*/ 10 LL Up_Date(LL n){/*向上更新,区间汇总*/ 11 return ID[2*n].Key+ID[2*n+1].Key; 12 } 13 void Down_Date(LL n){/*向下更新*/ 14 if(ID[n].Add!=0){ 15 ID[2*n].Add+=ID[n].Add; 16 ID[2*n+1].Add+=ID[n].Add; 17 ID[n].Key+=(ID[n].R-ID[n].L+1)*ID[n].Add; 18 ID[n].Add=0; 19 } 20 } 21 void Build(LL L,LL R,LL n)/*输入时建立二叉树根,Build(1,N,1)*/ 22 { 23 ID[n].L=L;ID[n].R=R; 24 ID[n].Add=0;ID[n].Key=0; 25 if (L==R){/*根据要求赋值*/ 26 scanf("%I64d",&ID[n].Key);return; 27 } 28 LL Mid=(L+R)/2; 29 Build(L,Mid,2*n);Build(Mid+1,R,2*n+1); 30 ID[n].Key=Up_Date(n); 31 } 32 33 void UpDate_L(LL L,LL R,LL n,LL v)/*区间更新,标记区间*/ 34 { 35 if(L==ID[n].L && R==ID[n].R){ 36 ID[n].Add+=v;return ; 37 } 38 ID[n].Key+=v*(R-L+1); 39 //Down_Date(n);/*可以每次更新,提高效率*/ 40 LL Mid=(ID[n].L+ID[n].R)/2; 41 if (Mid>=R) UpDate_L(L,R,n*2,v); 42 else if (Mid<L) UpDate_L(L,R,n*2+1,v); 43 else{ 44 UpDate_L(L,Mid,n*2,v); 45 UpDate_L(Mid+1,R,n*2+1,v); 46 } 47 } 48 49 LL Query(LL L,LL R,LL n)/*询问匹配区间*/ 50 { 51 if(L==ID[n].L && R==ID[n].R){ 52 return ID[n].Key+ID[n].Add*(R-L+1); 53 } 54 Down_Date(n); 55 LL Mid=(ID[n].L+ID[n].R)/2; 56 if (Mid>=R)return Query(L,R,n*2); 57 else if (Mid<L)return Query(L,R,n*2+1); 58 else{ 59 return Query(L,Mid,n*2)+Query(Mid+1,R,n*2+1); 60 } 61 } 62 int main() 63 { 64 char Str; 65 LL T,t=1,N,M,i; 66 LL A,B,C; 67 while(scanf("%I64d%I64d",&N,&M)!=EOF) 68 { 69 Build(1,N,1);Len=N; 70 for(i=0;i<M;i++){ 71 scanf(" %c",&Str); 72 switch(Str){ 73 case 'Q':scanf("%I64d%I64d",&A,&B);printf("%I64d\n",Query(A,B,1));break; 74 case 'C':scanf("%I64d%I64d%I64d",&A,&B,&C);UpDate_L(A,B,1,C);break; 75 } 76 } 77 } 78 return 0; 79 }
转载请备注:
**************************************
* 作者: Wurq
* 博客: https://www.cnblogs.com/Wurq/
* Gitee: https://gitee.com/wurq
**************************************
**************************************
* 作者: Wurq
* 博客: https://www.cnblogs.com/Wurq/
* Gitee: https://gitee.com/wurq
**************************************