[線段樹] 基於最大子段和
阿新 • • 發佈:2021-08-12
https://www.luogu.com.cn/problem/SP1043
#include <iostream> #include <cstdio> #include <algorithm> #include <cctype> #define re register #define ll long long #define Seg SegmentTree #define lson p<<1,l,mid #define rson p<<1|1,mid+1,r #define readd read<int>() using namespace std; const int maxn=5001000; template<typename T> inline T& read(){ T x=0; bool flag=false; register char ch=getchar(); while(!isdigit(ch)&&ch!='-') ch=getchar(); if(ch=='-') flag=true,ch=getchar(); while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); if(flag) return x=(~x+1); else return x; } struct SegmentTree{ int sum,qian,hou,dat; }t[maxn<<2]; int n,m; inline void update(int p){ t[p].sum=t[p<<1].sum+t[p<<1|1].sum; t[p].qian=max(t[p<<1].qian,t[p<<1].sum+t[p<<1|1].qian); t[p].hou=max(t[p<<1|1].hou,t[p<<1|1].sum+t[p<<1].hou); t[p].dat=max(max(t[p<<1].dat,t[p<<1|1].dat),t[p<<1].hou+t[p<<1|1].qian); } inline void build(int p,int l,int r){ if(l==r){ t[p].dat=t[p].sum=t[p].qian=t[p].hou=readd;//到了葉子,一邊讀一邊建樹 return; } int mid=(l+r)>>1; build(lson);build(rson); update(p);//還是回溯時更新 } //主函式來了 inline Seg query(int p,int l,int r,int x,int y){//查詢賦值 if(x<=l&&y>=r)return t[p]; int mid=(l+r)>>1; if(x>mid)return query(rson,x,y); if(y<=mid)return query(lson,x,y);//注意是<= else{ Seg ans,a,b; a=query(lson,x,y);b=query(rson,x,y); ans.sum=a.sum+b.sum; ans.dat=max(a.dat,a.hou+b.qian),ans.dat=max(ans.dat,b.dat); ans.qian=max(a.qian,a.sum+b.qian); ans.hou=max(b.hou,b.sum+a.hou); return ans; } } int main(){ n=readd; build(1,1,n); m=readd; for(re int i=1;i<=m;i++){ int x=readd,y=readd; cout<<query(1,1,n,x,y).dat<<endl; } return 0; }