洛谷4513 小白逛公園(線段樹)
阿新 • • 發佈:2018-12-16
【題目分析】
題意。。。很明顯看出要維護區間子序列最大值,那麼問題就在於如何在區間合併的時候更新區間子序列最大值。
可以推出,區間子序列最大值要麼是從最左邊開始的一段,要麼是最右邊向左的一段,要麼是中間的一段,對於第一種,我們發現要麼是左兒子最左邊的一段,要麼是左兒子+右兒子左邊一段,第二種同理。
對於第三種,要麼是左兒子的最大值,要麼是右兒子的最大值,要麼是左兒子的右邊的一段與右兒子的左邊的一段拼起來。
然後就over啦
【程式碼~】
#include<bits/stdc++.h> using namespace std; const int MAXN=5e5+10; struct Tree{ int l,r; int ls,rs,maxs; int sum; }tr[MAXN<<2]; int n,m; int scor[MAXN]; void push_up(int root) { tr[root].sum=tr[root<<1].sum+tr[root<<1|1].sum; tr[root].ls=max(tr[root<<1].ls,tr[root<<1].sum+tr[root<<1|1].ls); tr[root].rs=max(tr[root<<1|1].rs,tr[root<<1|1].sum+tr[root<<1].rs); tr[root].maxs=max(max(tr[root<<1].maxs,tr[root<<1|1].maxs),tr[root<<1].rs+tr[root<<1|1].ls); } void build(int root,int l,int r) { tr[root].l=l; tr[root].r=r; if(l==r) { tr[root].ls=tr[root].rs=tr[root].maxs=tr[root].sum=scor[l]; return ; } int mid=l+r>>1; build(root<<1,l,mid); build(root<<1|1,mid+1,r); push_up(root); } void update(int root,int l,int r,int x,int key) { if(l==r) { tr[root].ls=tr[root].rs=tr[root].maxs=tr[root].sum=key; return ; } int mid=l+r>>1; if(x<=mid) update(root<<1,l,mid,x,key); else update(root<<1|1,mid+1,r,x,key); push_up(root); } Tree query(int root,int L,int R) { if(L<=tr[root].l&&tr[root].r<=R) return tr[root]; int mid=tr[root].l+tr[root].r>>1; if(R<=mid) return query(root<<1,L,R); if(L>mid) return query(root<<1|1,L,R); Tree ans,ans1=query(root<<1,L,mid),ans2=query(root<<1|1,mid+1,R); ans.l=ans1.l,ans.r=ans2.r; ans.ls=max(ans1.ls,ans1.sum+ans2.ls); ans.rs=max(ans2.rs,ans2.sum+ans1.rs); ans.maxs=max(max(ans1.maxs,ans2.maxs),ans1.rs+ans2.ls); ans.sum=ans1.sum+ans2.sum; return ans; } int Read() { int i=0,f=1; char c; for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar()); if(c=='-') f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar()) i=(i<<3)+(i<<1)+c-'0'; return i*f; } int main() { n=Read(),m=Read(); for(int i=1;i<=n;++i) scor[i]=Read(); build(1,1,n); while(m--) { int cz=Read(),l=Read(),r=Read(); if(cz==1) { if(l>r) swap(l,r); printf("%d\n",query(1,l,r).maxs); } else update(1,1,n,l,r); } return 0; }