洛谷 P3372 模板线段树 1

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P3372 模板线段树 1相关的知识,希望对你有一定的参考价值。

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。

题目链接:https://www.luogu.org/problem/show?pid=3372

题目描述

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

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数据范围内)

 

 

分析:

带lazy标记的线段树模板。

 

 

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 
 6 using namespace std;
 7 const int MAXN = 100000 + 10;
 8 inline void read(int &x)
 9 {//快速读入
10     char ch = getchar();char c;x = 0;
11     while(ch > 9 || ch < 0)    c = ch,ch = getchar();
12     while(ch <= 9 && ch >= 0) x = x*10+ch-0,ch = getchar();
13 }
14 int n,m,num[MAXN];
15 long long stdata[MAXN << 2],stlazy[MAXN << 2];
16 void build(int o,int l,int r)
17 {//建立线段树
18     if(l == r)
19     {
20         stdata[o] = num[l];
21         return;
22     }
23     int mid = (l + r) >> 1;
24     build(o << 1,l,mid);
25     build(o << 1 | 1,mid + 1,r);
26     stdata[o] = stdata[o << 1] + stdata[o << 1|1];
27 }
28 
29 void putdown(int o,int l,int r)
30 {
31     stlazy[o << 1] += stlazy[o];
32     stlazy[o << 1|1] += stlazy[o];
33     int mid = (l + r) >> 1;
34     stdata[o << 1] += (mid - l + 1)*stlazy[o];
35     stdata[o << 1|1] += (r - mid)*stlazy[o];
36     stlazy[o] = 0;
37 }
38 
39 void s_modify(int ll,int rr,int k,int o,int l,int r)
40 {//区间修改
41     if(ll <= l && rr >= r)
42     {
43         stdata[o] += (r - l + 1)*k;
44         stlazy[o] += k;
45         return; 
46     }
47     int mid = (l + r) >> 1;
48     if(stlazy[o]) putdown(o,l,r);
49     if(mid >= ll)    s_modify(ll,rr,k,o << 1,l,mid);
50     if(mid < rr)    s_modify(ll,rr,k,o << 1|1,mid + 1,r);
51     stdata[o] = stdata[o << 1] + stdata[o << 1|1]; 
52 }
53 
54 long long ask(int ll,int rr,int o,int l,int r)
55 {//区间询问
56     if(ll <= l && rr >= r)
57         return stdata[o];
58     if(stlazy[o])    putdown(o,l,r);
59     int mid = (l + r) >> 1;
60     long long ans = 0;
61     if(mid >= ll) ans += ask(ll,rr,o << 1,l,mid);
62     if(mid < rr)  ans += ask(ll,rr,o << 1|1,mid + 1,r);
63     return ans;
64 }
65 
66 int main()
67 {
68     read(n),read(m);
69     for(int i = 1;i <= n;i ++)
70         read(num[i]);
71     build(1,1,n);
72     int op,x,y,k;
73     for(int i = 1;i <= m;i ++)
74     {
75         read(op);
76         if(op == 1)
77         {
78             read(x),read(y),read(k);
79             s_modify(x,y,k,1,1,n);
80         }
81         else
82         {
83             read(x),read(y);
84             long long t = ask(x,y,1,1,n);
85             printf("%lld\n",t);
86         }
87     }
88     return 0;
89 }

 

以上是关于洛谷 P3372 模板线段树 1的主要内容,如果未能解决你的问题,请参考以下文章

洛谷—— P3372 模板线段树 1

洛谷 P3372 模板线段树 1

洛谷P3372模板线段树 1

洛谷P3372 模板线段树 1(节省内存版)

线段树

P3372 模板线段树 1