題解 洛谷P4513 小白逛公園(線段樹)

2021-08-21 21:22:49 字數 1883 閱讀 9062

這裡要對某個葉子節點的值進行修改,最後求某一段區間內的某一段和的最大值,可以用線段樹來解決,但需要多開一些陣列儲存更多的資訊。

我們定義ln陣列記錄某個結點從左開始某一段區間和的最大值,定義rn陣列為某個結點從右開始某一段區間和的最大值,定義midd陣列記錄某個結點在中間的某一段區間和的最大值,sum陣列為子結點的和。這樣我們對於update陣列就需要新增一些東西。不難得到ln[now]=max(ln[now*2],sum[now*2]+ln[now*2+1]),用類似的方法分別更新rn、midd陣列,sum陣列的更新同一般線段樹。建樹時,我們需要對ln、rn、midd、sum陣列都進行初始化。在寫change函式時,由於我們是對單個點進行修改,所以不需要寫pushdown函式,只需要判斷到葉子節點時將其sum、midd、rn、ln值都改為k即可。比較困難的是query詢問函式,由於我們要返回四個值,一般的int肯定是滿足不了的,所以我們開乙個結構體,裡面存上和四個陣列所代表的意義相同的變數。如果當前區間在目標區間內,就強制轉化返回那四個數。否則我們定義結構體形式的lans、lanr代表做左邊子節點、右邊子節點,初始化sum為-1e9,方便判斷有沒有搜尋左子結點或右子節點,如果某個子結點sum為0就返回另乙個。如果都訪問到了,就定義結構體型別的ans,分別記錄其ll,rr,mm,sum,最後返回ans即可。在求答案時,我們只需要比較得到query函式的ll,rr,mm的最大值即可。注意讀入的兩個公園可能左邊的比右邊大,調換一下位置。

#include#include#includeusing namespace std;

const int maxn=500010;

int n,m;

int in[maxn];

int ln[maxn*8],rn[maxn*8],midd[maxn*8],sum[maxn*8];

struct edge

;void update(int now)

void build(int now,int l,int r)

int mid=(l+r)/2;

build(now*2,l,mid);

build(now*2+1,mid+1,r);

update(now);

}void change(int now,int l,int r,int x,int k)

int mid=(l+r)/2;

if(x<=mid) change(now*2,l,mid,x,k);

else change(now*2+1,mid+1,r,x,k);

update(now);

}edge query(int now,int l,int r,int x,int y); }

edge lans=;

edge lanr=;

int mid=(l+r)/2;

if(x<=mid) lans=query(now*2,l,mid,x,y);

if(mid+1<=y) lanr=query(now*2+1,mid+1,r,x,y);

if(lans.sum==-1e9) return lanr;

if(lanr.sum==-1e9) return lans;

edge ans;

ans.ll=max(lans.ll,lans.sum+lanr.ll);

ans.rr=max(lanr.rr,lanr.sum+lans.rr);

ans.mm=max(max(lans.mm,lanr.mm),lans.rr+lanr.ll);

ans.sum=lans.sum+lanr.sum;

return ans;

}int main()

build(1,1,n);

for(int i=1;i<=m;i++)

else

}return 0;

}

洛谷 P4513 小白逛公園

小新經常陪小白去公園玩,也就是所謂的遛狗啦 在小新家附近有一條 公園路 路的一邊從南到北依次排著nn個公園,小白早就看花了眼,自己也不清楚該去哪些公園玩了。一開始,小白就根據公園的風景給每個公園打了分 小新為了省事,每次遛狗的時候都會事先規定乙個範圍,小白只可以選擇第aa個和第bb個公園之間 包括a...

P4513 小白逛公園

小新經常陪小白去公園玩,也就是所謂的遛狗啦 在小新家附近有一條 公園路 路的一邊從南到北依次排著n nn個公園,小白早就看花了眼,自己也不清楚該去哪些公園玩了。一開始,小白就根據公園的風景給每個公園打了分 小新為了省事,每次遛狗的時候都會事先規定乙個範圍,小白只可以選擇第a aa個和第b bb個公園...

P4513 小白逛公園 線段樹

線段樹是一門比較刁鑽的手藝.此題我們需要維護 4 個變數 amx 代表當前節點的最大值.lmx 代表當前節點以左端點為起點的區間最大值.rmx 代表當前節點以右端點為結尾的區間最大值.sum 代表整段的和.然後我們在 push up 的時候,也是要做蠻多工作.lc 為左端點,rc 為右端點.lmx ...