線段樹是一門比較刁鑽的手藝...
此題我們需要維護 \(4\) 個變數:
\(amx\) 代表當前節點的最大值.
\(lmx\) 代表當前節點以左端點為起點的區間最大值.
\(rmx\) 代表當前節點以右端點為結尾的區間最大值.
\(sum\) 代表整段的和.
然後我們在 \(push\)_\(up\) 的時候,也是要做蠻多工作.
\(lc\) 為左端點,\(rc\) 為右端點.
\(lmx=max(lmx_,sum_+lmx_)\)
也就是說可以單獨取左兒子裡的最大值,也可以一直取到右兒子的 \(lmx\) 為止.
\(rmx=max(rmx_,sum_+rmx_)\)
和上文同理.
\(sum=sum_+sum_\)
\(amx=max(amx_,amx_,rmx_+lmx_)\)
最關鍵的一步,更新每乙個節點的答案. 可以在圖上自己理解,此處不贅述.
特別注意,查詢的時候也要把所有查出來的區間進行類似的操作...
#includeusing namespace std;
const int maxn=1000008;
struct node
sgm[maxn*4];
int n,m,k,x,y;
int cnt,a[maxn];
void push_up(int x)
void build(int l,int r,int now)
int mid=(l+r)>>1;
sgm[now].lc=2*now;
build(l,mid,sgm[now].lc);
sgm[now].rc=2*now+1;
build(mid+1,r,sgm[now].rc);
push_up(now);
}void change(int now,int to,int num)
int mid=(x+y)>>1;
if(to<=mid) change(sgm[now].lc,to,num);
else change(sgm[now].rc,to,num);
push_up(now);
}node query(int now,int l,int r)
}int main()
else change(1,x,y);
}return 0;
}
P4513 小白逛公園 線段樹
小新經常陪小白去公園玩,也就是所謂的遛狗啦 在小新家附近有一條 公園路 路的一邊從南到北依次排著nn個公園,小白早就看花了眼,自己也不清楚該去哪些公園玩了。一開始,小白就根據公園的風景給每個公園打了分 小新為了省事,每次遛狗的時候都會事先規定乙個範圍,小白只可以選擇第aa個和第bb個公園之間 包括a...
P4513 小白逛公園
小新經常陪小白去公園玩,也就是所謂的遛狗啦 在小新家附近有一條 公園路 路的一邊從南到北依次排著n nn個公園,小白早就看花了眼,自己也不清楚該去哪些公園玩了。一開始,小白就根據公園的風景給每個公園打了分 小新為了省事,每次遛狗的時候都會事先規定乙個範圍,小白只可以選擇第a aa個和第b bb個公園...
題解 洛谷P4513 小白逛公園(線段樹)
這裡要對某個葉子節點的值進行修改,最後求某一段區間內的某一段和的最大值,可以用線段樹來解決,但需要多開一些陣列儲存更多的資訊。我們定義ln陣列記錄某個結點從左開始某一段區間和的最大值,定義rn陣列為某個結點從右開始某一段區間和的最大值,定義midd陣列記錄某個結點在中間的某一段區間和的最大值,sum...