【模板】 递归线段树 [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 }
原文地址:https://www.cnblogs.com/huibixiaoxing/p/6930692.html