1. 程式人生 > >CODEVS 1081 線段樹練習 2 題解

CODEVS 1081 線段樹練習 2 題解

output lazy printf 區間修改 iostream getch spa turn 範圍

此文為博主原創題解,轉載時請通知博主,並把原文鏈接放在正文醒目位置。

題目鏈接: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 題解