标签:style blog color os io for 代码 div
这是个线段树题目,做之前必须要有些线段树基础才行不然你是很难理解的。
此题的难点就是在于你加的数要怎么加,加入你一直加到叶子节点的话,复杂度势必会很高的
具体思路
在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的Inc值,不再往下走,否则要更新Sum(加上本次增量),再将增量往下传。
这样更新的复杂度就是O(log(n))在查询时,如果待查区间不是正好覆盖一个节点,就将节点的Inc往下带,然后将Inc代表的所有增量累加到Sum上后将Inc清0,接下来再往下查询。
Inc往下带的过程也是区间分解的过程,复杂度也是O(log(n))
明白思路就好写了。
下面是代码
1 #include<stdio.h> 2 #include<iostream> 3 #include<stack> 4 #include<queue> 5 #include<math.h> 6 #include<stdlib.h> 7 #include<cstring> 8 using namespace std; 9 10 #define max(a,b) (a>b?a:b) 11 #define min(a,b) (a<b?a;b) 12 #define INF 0xffffff0 13 #define maxn 400010 14 15 struct Node 16 { 17 int L, R; 18 __int64 Sum, Inc; 19 int Mid() 20 { 21 return (L+R)/2; 22 } 23 }Tree[maxn];//这里我们用数组保存线段树 24 __int64 sum; 25 void BulidTree(int root,int L,int R); 26 void Insert(int root,int i,int v); 27 void Add(int root,int s,int e,int v); 28 void QuerySum(int root,int s,int e); 29 30 int main() 31 { 32 int Q, N, v; 33 scanf("%d%d",&N,&Q); 34 BulidTree(0,1,N); 35 for(int i = 1; i <= N; i++) 36 { 37 scanf("%d",&v); 38 Insert(0,i,v); 39 } 40 int s, e; 41 char str[2]; 42 while(Q--) 43 { 44 scanf("%s%d%d",str,&s,&e); 45 if(str[0] == ‘Q‘) 46 { 47 sum = 0; 48 QuerySum(0,s,e); 49 printf("%I64d\n",sum); 50 } 51 else 52 { 53 scanf("%d",&v); 54 Add(0,s,e,v); 55 } 56 } 57 return 0; 58 } 59 60 void BulidTree(int root,int L,int R) 61 { 62 Tree[root].L = L; 63 Tree[root].R = R; 64 Tree[root].Inc = Tree[root].Sum = 0; 65 if(L != R) 66 { 67 BulidTree(root*2+1,L,Tree[root].Mid()); 68 BulidTree(root*2+2,Tree[root].Mid()+1,R); 69 } 70 } 71 void Insert(int root,int i,int v) 72 { 73 if(Tree[root].L == Tree[root].R) 74 { 75 Tree[root].Sum = v; 76 return ; 77 } 78 Tree[root].Sum += v; 79 if(i <= Tree[root].Mid()) 80 Insert(root*2+1,i,v); 81 else 82 Insert(root*2+2,i,v); 83 } 84 void Add(int root,int s,int e,int v) 85 { 86 if(Tree[root].L == s && Tree[root].R == e) 87 { 88 Tree[root].Inc += v; 89 return ; 90 } 91 Tree[root].Sum += (e-s+1)*v; 92 if(e <= Tree[root].Mid()) 93 Add(2*root+1,s,e,v); 94 else if(s > Tree[root].Mid()) 95 Add(2*root+2,s,e,v); 96 else 97 { 98 Add(root*2+1,s,Tree[root].Mid(),v); 99 Add(root*2+2,Tree[root].Mid()+1,e,v); 100 } 101 } 102 void QuerySum(int root,int s,int e) 103 { 104 if(Tree[root].L == s && Tree[root].R == e) 105 { 106 sum += (Tree[root].R - Tree[root].L + 1)*Tree[root].Inc + Tree[root].Sum; 107 return ; 108 } 109 Tree[root].Sum += (Tree[root].R - Tree[root].L+1)*Tree[root].Inc; 110 if(Tree[root].Inc) 111 { 112 Tree[root*2+1].Inc += Tree[root].Inc; 113 Tree[root*2+2].Inc += Tree[root].Inc; 114 } 115 Tree[root].Inc = 0; 116 if(e <= Tree[root].Mid()) 117 QuerySum(root*2+1,s,e); 118 else if(s > Tree[root].Mid()) 119 QuerySum(root*2+2,s,e); 120 else 121 { 122 QuerySum(root*2+1,s,Tree[root].Mid()); 123 QuerySum(root*2+2,Tree[root].Mid()+1,e); 124 } 125 }
POJ 3468 A Simple Problem with Integers(详细题解),布布扣,bubuko.com
POJ 3468 A Simple Problem with Integers(详细题解)
标签:style blog color os io for 代码 div
原文地址:http://www.cnblogs.com/chenchengxun/p/3871605.html