码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3468 A Simple Problem with Integers(详细题解)

时间:2014-07-27 22:45:49      阅读:290      评论:0      收藏:0      [点我收藏+]

标签: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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!