關於動態最大子段和 線段樹查詢

2022-04-30 02:54:09 字數 2455 閱讀 2517

question:

有n個數,a[1]到a[n]。

接下來q次查詢,每次動態指定兩個數l,r,求a[l]到a[r]的最大子段和。

子段的意思是連續非空區間。

輸入描述 input description

第一行乙個數n。

第二行n個數a[1]~a[n]。

第三行乙個數q。

以下q行每行兩個數l和r。

輸出描述 output description

q行,每行乙個數,表示a[l]到a[r]的最大子段和。

樣例輸入 sample input

72 3 -233 233 -23 -2 233

41 7

5 62 5

2 3樣例輸出 sample output

441-2

2333

高效完成這個問題,可以用線段樹進行區間動態查詢最大欄位和

最大欄位和

線段樹實現

線段樹維護:

1. 區間最大欄位和

2. 從該區間的左端點開始的最大欄位和(一定包括該區間左端點)

3.   從該區間的右端點開始的最大欄位和(同理一定包括該區間右端點)

最大欄位和分布

1. 完全的包含於做區間

2. 完全的包含於右區間

3. 包含於左右區間

維護的2,3主要是用於處理分布為3的情況

合併:很好理解

查詢:當查詢區間完全處於當前區間的左側

查詢當前區間的左兒子

當查詢區間完全處於當前區間的右側

查詢當前區間的由兒子

否則說明查詢區間包含當前區間的mid

將ans等置為0,從當前區間的左右兒子開始查詢

會在3個黑圈處執行區間完全包含

從左到右依次編號1,2,3

會在1,2號return後進行一次ans, l_ans, r_ans 的賦max值

會在3好return後進行行一次ans, l_ans, r_ans 的賦max值

當遞迴到2,3節點時(注意這裡是節點),進行一次

ans = max(max(l_ans, r_ans), l_rans +r_lans);

l_ans = max(l_ans, t[jd << 1].w +r_lans);

r_ans = max(r_ans, t[jd << 1 | 1].w + l_rans);

結束後ans即為answer

#include #include 

#include

#include

#include

using

namespace

std;

const

int n = 4e6 + 1

;#define ll long long

#define zero 0

struct

node;

node t[n];

intn, m;

struct

r

while(c >= '

0' && c <= '

9') x = x * 10 + c - '

0', c =getchar();

return x *f;

}inline ll rell()

while(c >= '

0' && c <= '

9') x = x * 10 + c - '

0', c =getchar();

return x *f;

}}re;

void un(int

jd)void build_tree(int l, int r, int

jd)

int mid = (l + r) >> 1

; build_tree(l, mid, jd

<< 1

); build_tree(mid + 1, r, jd << 1 | 1

); un(jd);

}void q_ask(int l, int r, int jd, int x, int y, ll & ans, ll & l_ans, ll &r_ans)

int mid = (l + r) >> 1

;

if(y <= mid) q_ask(l, mid, jd << 1

, x, y, ans, l_ans, r_ans);

else

if(x > mid) q_ask(mid + 1, r, jd << 1 | 1

, x, y, ans, l_ans, r_ans);

else

}int

main()

return0;

}

區間最大子段和 線段樹

意思就是給你n個數,q次操作,每次改乙個值,或者詢問區間 l,r 內最大的連續子段和。線段樹維護四個東西,區間和,區間最大子段和,緊靠區間左端點的最大子段和,緊靠區間右端點的最大子段和。sum,lmax.rmax,dat,分別表示上述四種東西。sum不用說吧。對於lmax k 因為緊靠區間左端點,那...

線段樹維護最大子段和

查詢的時候返回一整個線段樹節點,而不是乙個值,這樣才有足夠的資訊去處理問題。因為最大子段和如果跨過一些節點,那麼這個最大子段和的資訊本身不一定可以被每個節點所代表的區間的最大子段和表示,所以需要合併一些節點的資訊。include using namespace std const int maxn ...

SGT 線段樹維護區間最大子段和

藍書p208 若將一區間分為兩部分,則必有最大子段存在於左區間 右區間 跨越中間 因此當前節點記錄該段的最大字首和,最大字尾和,段和,區間內最大子段和 now.sum ls.sum rs.sum now.lmax max ls.lmax,ls.sum rs.lmax now.rmax max rs....