zoukankan      html  css  js  c++  java
  • POJ 3468 线段树区间求和

    线段树区间求和树节点不能只存和,只存和,会导致每次加数的时候都要更新到叶子节点,速度太慢(O(nlogn))。所以我们要存两个量,一个是原来的和nSum,一个是累加的增量Inc。

    在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的Inc值,不再往下走,否则要更新nSum(加上本次增量),再将增量往下传,这样更新的复杂度就是O(log(n))。

     

    在查询时,如果待查区间不是正好覆盖一个节点,就将节点的Inc往下带,然后将Inc清0,接下来再往下查询。 Inc往下带的过程也是区间分解的过程,复杂度也是O(log(n))。                                                                                                                                                   
     
                                                                                       A Simple Problem with Integers
    Time Limit: 5000MS   Memory Limit: 131072K
    Total Submissions: 79334   Accepted: 24455
    Case Time Limit: 2000MS

    Description

    You have N integers, A1A2, ... , 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 A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
    Each of the next Q lines represents an operation.
    "C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
    "Q a b" means querying the sum of AaAa+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
      1 #include <iostream>
      2 #include<cstdio>
      3 using namespace std;
      4 struct CNode
      5 {
      6     int L ,R;
      7     CNode * pLeft, * pRight;
      8     long long nSum; //原来的和
      9     long long Inc; //增量c的累加
     10 };
     11 CNode Tree[200010]; // 2倍叶子节点数目就够
     12 int nCount = 0;
     13 int Mid( CNode * pRoot)
     14 {
     15     return (pRoot->L + pRoot->R)/2;
     16 }
     17 void BuildTree(CNode * pRoot,int L, int R)
     18 {
     19     pRoot->L = L;
     20     pRoot->R = R;
     21     pRoot->nSum = 0;
     22     pRoot->Inc = 0;
     23     if( L == R)
     24         return;
     25     nCount ++;
     26     pRoot->pLeft = Tree + nCount;
     27     nCount ++;
     28     pRoot->pRight = Tree + nCount;
     29     BuildTree(pRoot->pLeft,L,(L+R)/2);
     30     BuildTree(pRoot->pRight,(L+R)/2+1,R);
     31 }
     32 void Insert( CNode * pRoot,int i, int v)
     33 {
     34     if( pRoot->L == i && pRoot->R == i)
     35     {
     36         pRoot->nSum = v;
     37         return ;
     38     }
     39     pRoot->nSum += v;
     40     if( i <= Mid(pRoot))
     41         Insert(pRoot->pLeft,i,v);
     42     else
     43         Insert(pRoot->pRight,i,v);
     44 }
     45 void Add( CNode * pRoot, int a, int b, long long c)
     46 {
     47     if( pRoot->L == a && pRoot->R == b)
     48     {
     49         pRoot->Inc += c;
     50         return ;
     51     }
     52     pRoot->nSum += c * ( b - a + 1) ;
     53     if( b <= (pRoot->L + pRoot->R)/2)
     54         Add(pRoot->pLeft,a,b,c);
     55     else if( a >= (pRoot->L + pRoot->R)/2 +1)
     56         Add(pRoot->pRight,a,b,c);
     57     else
     58     {
     59         Add(pRoot->pLeft,a,
     60             (pRoot->L + pRoot->R)/2 ,c);
     61         Add(pRoot->pRight,
     62             (pRoot->L + pRoot->R)/2 + 1,b,c);
     63     }
     64 }
     65 long long QuerynSum( CNode * pRoot, int a, int b)
     66 {
     67     if( pRoot->L == a && pRoot->R == b)
     68         return pRoot->nSum +
     69                (pRoot->R - pRoot->L + 1) * pRoot->Inc ;
     70     pRoot->nSum += (pRoot->R - pRoot->L + 1) * pRoot->Inc ;
     71     Add( pRoot->pLeft,pRoot->L,Mid(pRoot),pRoot->Inc);
     72     Add( pRoot->pRight,Mid(pRoot) + 1,pRoot->R,pRoot->Inc);
     73     pRoot->Inc = 0;
     74     if( b <= Mid(pRoot))
     75         return QuerynSum(pRoot->pLeft,a,b);
     76     else if( a >= Mid(pRoot) + 1)
     77         return QuerynSum(pRoot->pRight,a,b);
     78     else
     79     {
     80         return QuerynSum(pRoot->pLeft,a,Mid(pRoot)) +
     81                QuerynSum(pRoot->pRight,Mid(pRoot) + 1,b);
     82     }
     83 }
     84 int main()
     85 {
     86     int n,q,a,b,c;
     87     char cmd[10];
     88     scanf("%d%d",&n,&q);
     89     int i,j,k;
     90     nCount = 0;
     91     BuildTree(Tree,1,n);
     92     for( i = 1; i <= n; i ++ )
     93     {
     94         scanf("%d",&a);
     95         Insert(Tree,i,a);
     96     }
     97     for( i = 0; i < q; i ++ )
     98     {
     99         scanf("%s",cmd);
    100         if ( cmd[0] == 'C' )
    101         {
    102             scanf("%d%d%d",&a,&b,&c);
    103             Add( Tree,a,b,c);
    104         }
    105         else
    106         {
    107             scanf("%d%d",&a,&b);
    108             printf("%I64d
    ",QuerynSum(Tree,a,b));
    109         }
    110     }
    111     return 0;
    112 }
    View Code
  • 相关阅读:
    react路由组件&&非路由组件
    react函数式组件(非路由组件)实现路由跳转
    react使用antd组件递归实现左侧菜单导航树
    【LeetCode】65. Valid Number
    【LeetCode】66. Plus One (2 solutions)
    【LeetCode】68. Text Justification
    【LeetCode】69. Sqrt(x) (2 solutions)
    【LeetCode】72. Edit Distance
    【LeetCode】73. Set Matrix Zeroes (2 solutions)
    【LeetCode】76. Minimum Window Substring
  • 原文地址:https://www.cnblogs.com/zero-zz/p/4811331.html
Copyright © 2011-2022 走看看