• 【模板】 递归线段树 [2017年五月计划 清北学堂51精英班Day4]


    P3372 【模板】线段树 1

    题目描述

    如题,已知一个数列,你需要进行下面两种操作:

    1.将某区间每一个数加上x

    2.求出某区间每一个数的和

    输入输出格式

    输入格式:

    第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

    第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

    接下来M行每行包含3或4个整数,表示一个操作,具体如下:

    操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k

    操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和

    输出格式:

    输出包含若干行整数,即为所有操作2的结果。

    输入输出样例

    输入样例#1:
    5 5
    1 5 4 2 3
    2 2 4
    1 2 3 2
    2 3 4
    1 1 5 1
    2 1 4
    输出样例#1:
    11
    8
    20

    说明

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据:N<=8,M<=10

    对于70%的数据:N<=1000,M<=10000

    对于100%的数据:N<=100000,M<=100000

    (数据已经过加强^_^,保证在int64/long long数据范围内)

    样例说明:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #define max(a,b) ((a) > (b) ? (a) : (b))
      7 #define min(a,b) ((a) > (b) ? (b) : (a))
      8 #define lowbit(a) (a & (-(a)))
      9 const int INF = 0x3f3f3f3f;
     10 const int MAXN = 100000 + 10;
     11 const int MAXM = 100000 + 10;
     12 inline void read(long long &x)
     13 {
     14     x = 0;char ch = getchar();char c = ch;
     15     while(ch > '9' || ch < '0')c = ch, ch = getchar();
     16     while(ch >= '0' && ch <= '9')x = x * 10 + ch - '0',ch = getchar();
     17     if(c == '-')x = -x;
     18 }
     19 
     20 long long stdata[MAXN << 2];
     21 long long stlazy[MAXN << 2];
     22 long long n,m;
     23 
     24 
     25 void modify1(long long p, long long k, long long o = 1,long long l = 1,long long r = n)
     26 {
     27     if(l == r == p)
     28     {
     29         stdata[o] += k;
     30         return;
     31     }
     32     long long mid = (l + r) >> 1;
     33     if(p <= mid) modify1(p, k, o << 1, l, mid);
     34     else modify1(p, k, o << 1 | 1, mid + 1, r);
     35     stdata[o] = stdata[o << 1] + stdata[o << 1 | 1];
     36     return ;
     37 }
     38 
     39 
     40 void modify2(long long ll, long long rr, long long k, long long o = 1, long long l = 1, long long r = n)
     41 {
     42     if(l >= ll && r <= rr)
     43     {
     44         stlazy[o] += k;
     45         stdata[o] += (r - l + 1) * k;
     46         return;
     47     }
     48     if(ll <= l && rr <= r && rr >= l)
     49     {
     50         stdata[o] += k * (rr - l + 1);
     51     }
     52     else if(ll >= l && rr <= r)
     53     {
     54         stdata[o] += k * (rr - ll + 1);
     55     }
     56     else if(ll >= l && ll <= r && rr >= r)
     57     {
     58         stdata[o] += k * (r - ll + 1);
     59     }
     60     long long mid = (l + r) >> 1;
     61     if(ll <= mid)modify2(ll, rr, k, o << 1, l, mid);
     62     if(rr > mid) modify2(ll, rr, k, o << 1 | 1, mid + 1, r);
     63 }
     64 
     65 long long query(long long ll, long long rr, long long o = 1, long long l = 1, long long r = n)
     66 {
     67     long long mid = (l + r) >> 1;
     68     if(ll <= l && rr >= r)
     69     {
     70         return stdata[o];
     71     }
     72     if(stlazy[o])
     73     {
     74         stlazy[o << 1] += stlazy[o];
     75         stlazy[o << 1 | 1] += stlazy[o];
     76         stdata[o << 1] += (mid - l + 1) * stlazy[o];
     77         stdata[o << 1 | 1] += (r - mid) * stlazy[o];
     78         stlazy[o] = 0;
     79     }
     80     long long ans = 0;
     81     if(ll <= mid)ans += query(ll, rr, o << 1, l, mid);
     82     if(rr > mid) ans += query(ll, rr, o << 1 | 1, mid + 1, r);
     83     stdata[o] = stdata[o << 1] + stdata[o << 1 | 1];
     84     return ans;
     85 }
     86 
     87 long long num[MAXN];
     88 long long cnt;
     89 void build(long long o = 1,long long l = 1,long long r = n)
     90 {
     91     if(l == r)
     92     {
     93         stdata[o] = num[++cnt];
     94         return;
     95     }
     96     long long mid = (l + r) >> 1;
     97     build(o << 1, l, mid);
     98     build(o << 1 | 1, mid + 1, r);
     99     stdata[o] = stdata[o << 1] + stdata[o << 1 | 1];
    100 }
    101 
    102 long long tmp1,tmp2,tmp3,tmp4;
    103 
    104 int main()
    105 {
    106     read(n);read(m);
    107     for(long long i = 1;i <= n;i ++)
    108     {
    109         read(num[i]);
    110     }
    111     build();
    112     for(long long i = 1;i <= m;i ++)
    113     {
    114         read(tmp1);
    115         switch(tmp1)
    116         {
    117             case 1:
    118                 {
    119                     read(tmp1);read(tmp2);read(tmp3);
    120                     modify2(tmp1, tmp2, tmp3);
    121                     break;
    122                 }
    123             case 2:
    124                 {
    125                     read(tmp1);read(tmp2);
    126                     printf("%lld
    ", query(tmp1, tmp2));
    127                 }
    128         }
    129     }
    130     return 0;
    131 }
  • 相关阅读:
    微信小程序scroll-view不动的处理
    AndoridSQLite数据库开发基础教程(4)
    Andorid SQLite数据库开发基础教程(3)
    Andorid SQLite数据库开发基础教程(2)
    Visual Studio 2019更新到16.2.3
    密码的复杂化#个人隐私保护系列#
    Nessus更新到8.6.0
    Visual Studio 2019更新到16.2.2
    Maltego更新到4.2.6
    Visual Studio 2019更新到16.2.1
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/6930692.html
Copyright © 2020-2023  润新知