• A Simple Problem with Integers


    A Simple Problem with Integers
    Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u

    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 abc" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
    "Q ab" 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

    Hint

    The sums may exceed the range of 32-bit integers.
    区间更新;
      1 #include<iostream>
      2 #include<cstdio>
      3 
      4 using namespace std;
      5 
      6 #define N 210000
      7 
      8 struct node
      9 {
     10     long long l, r, sum, op, e;  // op 代表是否更新,e代表要更新的数是多少
     11     int len(){return (r-l+1);}  // 区间长度
     12 }tree[N*4];
     13 
     14 long long cnt[N];
     15 
     16 void Build(int root, int l, int r)
     17 {
     18     tree[root].l = l;
     19     tree[root].r = r;
     20     tree[root].op = -1;  // 初始化全部不需要更新
     21     tree[root].e = 0;   // 需要加的值为0
     22 
     23     if(tree[root].l == tree[root].r) 
     24     {
     25         tree[root].sum = cnt[l];  // 到叶子节点时总和就是自身
     26         return ;
     27     }
     28     Build(2*root, l, (l+r)/2);
     29     Build(2*root+1, (l+r)/2+1, r);
     30     tree[root].sum = tree[root*2].sum + tree[root*2+1].sum;  // 这棵树上的和等于左儿子和右儿子的总和
     31 }
     32 
     33 void Down(int root)  // 向下更新
     34 {
     35     if(tree[root].op && tree[root].l != tree[root].r)
     36     {
     37         tree[root].op = false;
     38 
     39         tree[root*2].op = tree[root*2+1].op = true;
     40         tree[root*2].e += tree[root].e;
     41         tree[root*2+1].e += tree[root].e;
     42 
     43         tree[root*2].sum += tree[root].e*tree[root*2].len();
     44         tree[root*2+1].sum += tree[root].e*tree[root*2+1].len();
     45 
     46         tree[root].e = 0;
     47 
     48     }
     49 }
     50 
     51 void update(int root, int a, int b, int e)
     52 {
     53     Down(root); // 每次都可能会向下更新
     54 
     55     tree[root].sum += (b-a+1)*e;  // 这棵树上要家的值是a~b的长度乘以每一个数要加的e,因为这棵树上肯定包括这个区间(否则不会到这棵树上,所以这棵树上的总和要加上
     56 
     57     if(tree[root].l == a && tree[root].r == b)  // 如果这颗树上所有的数都要加数,更新,那么就把这颗树上的op置为1,意味着下边的树要更新,要向下Down,同时就不要向下update了,直接return就行
     58     { 
     59         tree[root].e = e;  // 这棵树上要更新的值为e
     60         tree[root].op = true;
     61         return ;
     62     }
     63     int mid = (tree[root].l+tree[root].r)/2;
     64 
     65     if(b <= mid)
     66         update(2*root, a, b, e);
     67     else if(a > mid)
     68         update(2*root+1, a, b, e);
     69     else
     70     {
     71         update(2*root, a, mid, e);
     72         update(2*root+1, mid+1, b, e);
     73     }
     74 
     75     tree[root].sum = tree[root*2].sum + tree[root*2+1].sum;  // 树上总和等于两个儿子总和
     76 }
     77 
     78 long long query(int root, int l, int r)  // 计算l~r的和
     79 {
     80     if(tree[root].l == l && tree[root].r == r) 
    82
    return tree[root].sum;
    84
    85 Down(root); //如果需要也要向下更新 86 87 int mid = (tree[root].l+tree[root].r)/2; 88 89 if(r <= mid) 90 return query(2*root, l, r); 91 else if(l > mid) 92 return query(2*root+1, l, r); 93 return query(root*2, l, mid)+query(root*2+1, mid+1, r); 94 } 95 int main() 96 { 97 long long n, q, a, b, c; 98 char s[9]; 99 100 while(scanf("%lld%lld", &n, &q) != EOF) 101 { 102 for(int i = 1; i <= n; i++) 103 scanf("%lld", &cnt[i]); 104 105 Build(1, 1, n); 106 107 while(q--) 108 { 109 scanf("%s", s); 110 111 if(s[0] == 'Q') 112 { 113 scanf("%lld%lld", &a, &b); 114 printf("%lld ", query(1, a, b)); 115 } 116 else if(s[0] =='C') 117 { 118 scanf("%lld%lld%lld", &a, &b, &c); 119 update(1, a, b, c); 120 } 121 } 122 } 123 return 0; 124 }

     也可以这么做:www.cnblogs.com/alihenaixiao/p/4611575.html

    解题思路:

      线段树更新到每一个节点的话,由于节点数目和查询次数原因会tle,所以在每一个节点内定义一个标志变量表示当前节点的下一层为更新,每次查询时候有需要的话在更新到下一层。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 using namespace std;
      6 const int maxn = 400010;
      7 const int INF = 0x3f3f3f3f;
      8 #define LL __int64
      9 struct node
     10 {
     11     LL L, R;
     12     LL sum, add;
     13     LL Mid()
     14     {
     15         return (L + R) / 2;
     16     }
     17 };
     18 node tree[maxn];
     19 LL res;
     20 
     21 void build(LL root, LL l, LL r)
     22 {
     23     tree[root].L = l;
     24     tree[root].R = r;
     25     tree[root].sum = tree[root].add = 0;
     26 
     27     if (l == r)
     28         return ;
     29     build (2*root+1, l, tree[root].Mid());
     30     build (2*root+2, tree[root].Mid()+1, r);
     31 }
     32 void insert (LL root, LL s, LL e, LL x)
     33 {
     34     tree[root].sum += x * (e - s + 1);
     35     if (tree[root].L == s && e == tree[root].R)//更新到区间
     36         {
     37             tree[root].add += x;
     38             return ;
     39         }
     40     if (e <= tree[root].Mid())
     41         insert (2*root+1, s, e, x);
     42     else if (tree[root].Mid() < s)
     43         insert (2*root+2, s, e, x);
     44     else
     45     {
     46         insert (2*root+1, s, tree[root].Mid(), x);
     47         insert (2*root+2, tree[root].Mid()+1, e, x);
     48     }
     49 }
     50 void query (LL root, LL s, LL e)
     51 {
     52 
     53     if (tree[root].L == s && e == tree[root].R)
     54     {
     55         res += tree[root].sum;
     56         return ;
     57     }
     58     if (tree[root].add)
     59     {//向下继续更新
     60         tree[2*root+1].add += tree[root].add;
     61         tree[2*root+2].add += tree[root].add;
     62         tree[2*root+1].sum += tree[root].add * (tree[2*root+1].R - tree[2*root+1].L + 1);
     63         tree[2*root+2].sum += tree[root].add * (tree[2*root+2].R - tree[2*root+2].L + 1);
     64         tree[root].add = 0;
     65     }
     66     if (e <= tree[root].Mid())
     67         query (2*root+1, s, e);
     68     else if (tree[root].Mid() < s)
     69         query (2*root+2, s, e);
     70     else
     71     {
     72         query (2*root+1, s, tree[root].Mid());
     73         query (2*root+2, tree[root].Mid()+1, e);
     74     }
     75 }
     76 int main ()
     77 {
     78     LL n, m, num;
     79     while (scanf ("%I64d %I64d", &n, &m) != EOF)
     80     {
     81         build (0, 1, n);
     82         for (int i=1; i<=n; i++)
     83         {
     84             scanf ("%I64d", &num);
     85             insert (0, i, i, num);
     86         }
     87         char str[2];
     88         LL s, e;
     89         while (m --)
     90         {
     91             scanf ("%s %I64d %I64d", str, &s, &e);
     92             if (str[0] == 'Q')
     93             {
     94                 res = 0;
     95                 query (0, s, e);
     96                 printf ("%I64d
    ", res);
     97             }
     98             else
     99             {
    100                 scanf ("%I64d", &num);
    101                 insert (0, s, e, num);
    102             }
    103         }
    104     }
    105     return 0;
    106 }
    让未来到来 让过去过去
  • 相关阅读:
    Day00课程前奏
    bootstrap前端框架
    html5标签
    js个人笔记
    css88
    小说拆分器
    什么是依赖注入
    与Java的约会
    Dom4J两种节点添加方法比较
    nodejs + typescript + koa + eslint + typescript eslint + prettier + webstorm
  • 原文地址:https://www.cnblogs.com/Tinamei/p/4699947.html
Copyright © 2020-2023  润新知