A Simple Problem with Integers
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 58269 | Accepted: 17753 | |
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
线段树,区间修改求和。
题意:
思路:
代码:
1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 5 #define MAXN 100010 6 7 struct Node{ 8 long long L,R; 9 long long sum; //当前区间的所有数的和 10 long long inc; //累加量 11 }a[MAXN*3]; 12 13 void Build(long long d,long long l,long long r) //建立线段树 14 { 15 16 //初始化当前节点的信息 17 a[d].L = l; 18 a[d].R = r; 19 a[d].inc = 0; 20 21 if(l==r){ //找到叶子节点 22 scanf("%I64d",&a[d].sum); 23 return ; 24 } 25 26 //建立线段树 27 long long mid = (l+r)>>1; 28 Build(d<<1,l,mid); 29 Build(d<<1|1,mid+1,r); 30 31 //更新当前节点的信息 32 a[d].sum = a[d<<1].sum + a[d<<1|1].sum; 33 } 34 35 void Updata(long long d,long long l,long long r,long long v) //更新区间[l,r]的累加量为v 36 { 37 if(a[d].L==l && a[d].R==r){ //找到终止节点 38 a[d].inc += v; 39 return ; 40 } 41 42 long long mid = (a[d].L+a[d].R)/2; 43 a[d].sum += a[d].inc*(a[d].R - a[d].L + 1); 44 45 if(mid>=r){ //左孩子找 46 Updata(d<<1,l,r,v); 47 } 48 else if(mid<l){ //右孩子找 49 Updata(d<<1|1,l,r,v); 50 } 51 else{ //左孩子、右孩子都找 52 Updata(d<<1,l,mid,v); 53 Updata(d<<1|1,mid+1,r,v); 54 } 55 56 a[d].sum = a[d<<1].sum + a[d<<1|1].sum 57 + a[d<<1].inc*(a[d<<1].R - a[d<<1].L + 1) 58 + a[d<<1|1].inc*(a[d<<1|1].R - a[d<<1|1].L + 1); 59 } 60 61 long long Query(long long d,long long l,long long r) //查询区间[l,r]的所有数的和 62 { 63 if(a[d].L==l && a[d].R==r){ //找到终止节点 64 return a[d].sum + a[d].inc * (r-l+1); 65 } 66 67 long long mid = (a[d].L+a[d].R)/2; 68 //更新每个节点的sum 69 a[d].sum += a[d].inc * (a[d].R - a[d].L + 1); 70 a[d<<1].inc += a[d].inc; 71 a[d<<1|1].inc += a[d].inc; 72 a[d].inc = 0; 73 74 //Updata(d<<1,a[d<<1].L,a[d<<1].R,a[d].inc); 75 //Updata(d<<1|1,a[d<<1|1].L,a[d<<1|1].R,a[d].inc); 76 77 if(mid>=r){ //左孩子找 78 return Query(d<<1,l,r); 79 } 80 else if(mid<l){ //右孩子找 81 return Query(d<<1|1,l,r); 82 } 83 else{ //左孩子、右孩子都找 84 return Query(d<<1,l,mid) + Query(d<<1|1,mid+1,r); 85 } 86 a[d].sum = a[d<<1].sum + a[d<<1|1].sum 87 + a[d<<1].inc*(a[d<<1].R - a[d<<1].L + 1) 88 + a[d<<1|1].inc*(a[d<<1|1].R - a[d<<1|1].L + 1); 89 } 90 91 int main() 92 { 93 long long n,q,A,B; 94 long long v; 95 scanf("%I64d%I64d",&n,&q); 96 Build(1,1,n); 97 while(q--){ //q次询问 98 char c[10]; 99 scanf("%s",&c); 100 switch(c[0]){ 101 case ‘Q‘: 102 scanf("%I64d%I64d",&A,&B); 103 printf("%I64d\n",Query(1,A,B)); //输出区间[A,B]所有数的和 104 break; 105 case ‘C‘: 106 scanf("%I64d%I64d%I64d",&A,&B,&v); 107 Updata(1,A,B,v); 108 break; 109 default:break; 110 } 111 } 112 return 0; 113 }
Freecode : www.cnblogs.com/yym2013
poj 3468:A Simple Problem with Integers(线段树,区间修改求和)