CODEVS 1081 线段树练习 2 题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CODEVS 1081 线段树练习 2 题解相关的知识,希望对你有一定的参考价值。

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

题目链接:http://codevs.cn/problem/1081/

题目描述 Description

给你N个数,有两种操作


1:给区间[a,b]的所有数都增加X


2:询问第i个数是什么?

输入描述 Input Description

第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。

输出描述 Output Description

对于每个询问输出一行一个答案

样例输入 Sample Input

3

1

2

3

2

1 2 3 2

2 3

样例输出 Sample Output

5

数据范围及提示 Data Size & Hint

数据范围

1<=n<=100000

1<=q<=100000

 

分析:

区间修改的线段树,使用lazy标记。反正是个板子qwq

 

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 
 6 const int MAXN = 100005;
 7 
 8 inline void read(int &x)
 9 {
10     char ch = getchar(),c = ch;x = 0;
11     while(ch < 0 || ch > 9) c = ch,ch = getchar();
12     while(ch <= 9 && ch >= 0) x = (x<<1)+(x<<3)+ch-0,ch = getchar();
13     if(c == -) x = -x;
14 }
15 
16 int num[MAXN],sdata[MAXN<<2],slazy[MAXN<<2];
17 
18 inline void update(int o)
19 {
20     sdata[o] = sdata[o<<1] + sdata[o<<1|1];
21 }
22 
23 void build(int l,int r,int o)
24 {
25     if(l == r)
26     {
27         sdata[o] = num[l];
28         return;
29     }
30     int mid = (l+r)>>1;
31     build(l,mid,o<<1);
32     build(mid+1,r,o<<1|1);
33     update(o);
34 }
35 
36 void putdown(int l,int r,int o)
37 {
38     slazy[o<<1] += slazy[o];
39     slazy[o<<1|1] += slazy[o];    
40     int mid = (l+r) >> 1;
41     sdata[o<<1] += (mid-l+1)*slazy[o];
42     sdata[o<<1|1] += (r-mid)*slazy[o]; 
43     slazy[o] = 0;
44 }
45 
46 void change(int l,int r,int o,int ll,int rr,int k)
47 {
48     if(ll <= l && rr >= r)
49     {
50         sdata[o] += (r-l+1)*k;
51         slazy[o] += k;
52         return;
53     }
54     if(slazy[o]) putdown(l,r,o);
55     int mid = (l+r)>>1;
56     if(mid >= ll) change(l,mid,o<<1,ll,rr,k);
57     if(mid < rr) change(mid+1,r,o<<1|1,ll,rr,k);
58     update(o);
59 }
60 
61 int ask(int l,int r,int o,int p)
62 {
63     if(l == r && r == p)
64     {
65         return sdata[o];
66     }
67     if(slazy[o]) putdown(l,r,o);
68     int mid = (l+r)>>1;
69     int ans = 0; 
70     if(p <= mid) ans = ask(l,mid,o<<1,p);
71     else ans = ask(mid+1,r,o<<1|1,p);
72     return ans; 
73 }
74 
75 int main()
76 {
77     int n,m,op,a,b,c;
78     read(n);
79     for(int i = 1;i <= n;++ i)
80         read(num[i]);
81     build(1,n,1);
82     read(m);
83     for(int i = 1;i <= m;++ i)
84     {
85         read(op);
86         if(op == 1)
87         {
88             read(a),read(b),read(c);
89             change(1,n,1,a,b,c);
90         }
91         else
92         {
93             read(a);
94             printf("%d\n",ask(1,n,1,a));
95         }
96     }
97     return 0;
98 }

 

以上是关于CODEVS 1081 线段树练习 2 题解的主要内容,如果未能解决你的问题,请参考以下文章

[Codevs] 1081 线段树练习 2 ----“分块!”

codevs1081 线段树练习 2

Codevs 1081 线段树练习2

1081 线段树练习 2

CODEVS 1080 线段树练习 题解

线段树模板合集(CodeVS1080 1081 1082 4597)Pascal代码