zoukankan      html  css  js  c++  java
  • 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 }
    让未来到来 让过去过去
  • 相关阅读:
    winform制作自定义控件(入门)
    VB2012读取xml
    VB生成xml
    通宵疯狂积累VB.NET基础知识
    【转】vs2010下创建webservice
    React Native 快速入门之认识Props和State
    mac下 mysql / nginx 问题总汇
    Oracle例外定义
    mac os x 把reids nignx mongodb做成随机启动吧
    Oracle 记录
  • 原文地址:https://www.cnblogs.com/Tinamei/p/4699947.html
Copyright © 2011-2022 走看看