此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。
题目链接: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 }
时间: 2024-11-08 19:47:06