4927 線段樹練習5

2022-05-09 17:28:58 字數 3613 閱讀 2738

時間限制: 1 s

空間限制: 128000 kb

題目等級 : ** gold

題解檢視執行結果

有n個數和5種操作

add a b c:把區間[a,b]內的所有數都增加c

set a b c:把區間[a,b]內的所有數都設為c

sum a b:查詢區間[a,b]的區間和

max a b:查詢區間[a,b]的最大值

min a b:查詢區間[a,b]的最小值

輸入描述 input description

第一行兩個整數n,m,第二行n個整數表示這n個數的初始值

接下來m行操作,同題目描述

輸出描述 output description

對於所有的sum、max、min詢問,一行輸出乙個答案

樣例輸入 sample input

10 6

3 9 2 8 1 7 5 0 4 6

add 4 9 4

set 2 6 2

add 3 8 2

sum 2 10

max 1 7

min 3 6

樣例輸出 sample output

資料範圍及提示 data size & hint

10%:130%:1100%:1保證中間結果在long long(c/c++)、int64(pascal)範圍內

ps:由於資料6出錯導致某些人只有90分,已於2016.5.13修正。

出題人在此對兩位90分的使用者表示誠摯的歉意

好噁心的一道題

這道題特殊在set操作

對於這個操作,我們需要增加兩個變數來維護,乙個維護這個區間是否被修改,乙個維護被修改成了多少

特別注意不能只維護被修改成了多少(會有0的情況)

在下傳標記的時候,需要先下傳set標記,再下傳add標記

因為我們在設定set標記的時候已經把add標記置為0

如果此時add標記不為0,就說明這個標記一定是在set標記設定之後設定的

再注意一下細節就可以了

1 #include2 #include3 #include4 #include5

#define ll long long

6#define ls k<<1

7#define rs k<<1|1

8using

namespace

std;

9const ll maxn=400400;10

const ll inf =0x7fffff

;11 inline void read(ll &n)

1217

struct

node

18tree[maxn];

22ll n,m;

23 ll ans=0

;24 inline void

update(ll k)

2530

void

build_tree(ll ll,ll rr,ll k)

3140 ll mid=tree[k].l+tree[k].r>>1;41

build_tree(ll,mid,ls);

42 build_tree(mid+1

,rr,rs);

43update(k);44}

45void

down(ll k)

4661

if(tree[k].add)

627475}

76void

interval_add(ll k,ll ll,ll rr,ll val)

7786

if(tree[k].add||tree[k].v) down(k);

87 ll mid=tree[k].r+tree[k].l>>1;88

if(ll<=mid) interval_add(ls,ll,rr,val);

89if(rr>mid) interval_add(rs,ll,rr,val);

90update(k);91}

92void

interval_change(ll k,ll ll,ll rr,ll val)

93102

if(tree[k].add||tree[k].v) down(k);

103 ll mid=tree[k].r+tree[k].l>>1

;104

if(ll<=mid) interval_change(ls,ll,rr,val);

105if(rr>mid) interval_change(rs,ll,rr,val);

106update(k);

107}

108void

interval_sum(ll k,ll ll,ll rr)

109115

if(tree[k].add||tree[k].v) down(k);

116 ll mid=tree[k].r+tree[k].l>>1

;117

if(ll<=mid) interval_sum(ls,ll,rr);

118if(rr>mid) interval_sum(rs,ll,rr);

119}

120void

interval_max(ll k,ll ll,ll rr)

121127

if(tree[k].add||tree[k].v) down(k);

128 ll mid=tree[k].r+tree[k].l>>1

;129

if(ll<=mid) interval_max(ls,ll,rr);

130if(rr>mid) interval_max(rs,ll,rr);

131}

132void

interval_min(ll k,ll ll,ll rr)

133139

if(tree[k].add||tree[k].v) down(k);

140 ll mid=tree[k].r+tree[k].l>>1

;141

if(ll<=mid) interval_min(ls,ll,rr);

142if(rr>mid) interval_min(rs,ll,rr);

143}

144int

main()

145157

else

if(how[0]=='

s'&&how[1]=='

e')//

區間賦值

158162

else

if(how[0]=='

s'&&how[1]=='

u')//

區間求和

163168

else

if(how[0]=='

m'&&how[1]=='

a')//

區間最大值

169174

else

if(how[0]=='

m'&&how[1]=='

i')//

區間最小值

175

180}

181return0;

182 }

4927 線段樹練習5

4927 線段樹練習5 時間限制 1 s 空間限制 128000 kb 題目等級 gold 題解 檢視執行結果 題目描述 description 有n個數和5種操作 add a b c 把區間 a,b 內的所有數都增加c set a b c 把區間 a,b 內的所有數都設為c sum a b 查詢區...

4927 線段樹練習5 多重標記

時間限制 1 s 空間限制 128000 kb 題目等級 gold 題解檢視執行結果 有n個數和5種操作 add a b c 把區間 a,b 內的所有數都增加c set a b c 把區間 a,b 內的所有數都設為c sum a b 查詢區間 a,b 的區間和 max a b 查詢區間 a,b 的最...

線段樹練習5(codevs 4927)

題目描述 description 有n個數和5種操作 add a b c 把區間 a,b 內的所有數都增加c set a b c 把區間 a,b 內的所有數都設為c sum a b 查詢區間 a,b 的區間和 max a b 查詢區間 a,b 的最大值 min a b 查詢區間 a,b 的最小值 輸...