題意:在乙個二維座標系上給你n(n<=2000)個點,點帶有乙個價值w(有正有負),點的座標都在(-1e9,1e9)的範圍之間,可任意用乙個平行於座標軸的矩形框住一片區域,求這片區域框住的點的價值和
分析:點的座標範圍太大,離散化應能想到。離散化後可以考慮列舉左邊界,列舉左邊界後按照橫座標的依次加點(以一列一列為單位),用線段樹維護一列的最大子段和,每移動到新的一列,繼續加點時,等價於向原先的那一列資料新增了值,每加完一列時,用乙個全域性變數ans來和當前列(此時已包含了好幾列了,其實本質上是乙個矩形)的最大子段和作比較,若ans小,則更新。
關於線段樹維護區間最大子段和:
本題,我們設ls為左端點起始的最大子段和,rs為右端點起始的最大子段和,ans為區間最大子段和,sum為區間和,維和方法可見前面這個部落格,也可直接看**。
#include usingnamespace
std;
typedef
long
long
ll;const
int mod=1e9+7
;const
int inf=1
<<30
;const
int maxn=2010
;ll ls[maxn
<<2],rs[maxn<<2],ans[maxn<<2],sum[maxn<<2
];struct
node
}a[maxn];
void build(int k,int l,int
r)void pushup(int
x)void update(int k,int l,int r,int pos,int
z)
int mid=(l+r)>>1
;
if(pos<=mid) update(k<<1
,l,mid,pos,z);
else update(k<<1|1,mid+1
,r,pos,z);
pushup(k);
}int
tx[maxn],ty[maxn];
intmain()
sort(tx+1,tx+n+1
);
int mx=unique(tx+1,tx+n+1)-tx-1
; sort(ty+1,ty+n+1
);
int my=unique(ty+1,ty+n+1)-ty-1
;
for(int i=1;i<=n;i++)
//以上這些步驟都是將橫縱座標離散化
ll ans=0;//
用來記錄答案
sort(a+1,a+n+1);//
按x排序,之後依次列舉左邊界
for(int i=1;i<=n;i++)
ans=max(ans,ans[1
]); }
}printf(
"%lld\n
",ans);
}}
SGT 線段樹維護區間最大子段和
藍書p208 若將一區間分為兩部分,則必有最大子段存在於左區間 右區間 跨越中間 因此當前節點記錄該段的最大字首和,最大字尾和,段和,區間內最大子段和 now.sum ls.sum rs.sum now.lmax max ls.lmax,ls.sum rs.lmax now.rmax max rs....
線段樹維護最大子段和
查詢的時候返回一整個線段樹節點,而不是乙個值,這樣才有足夠的資訊去處理問題。因為最大子段和如果跨過一些節點,那麼這個最大子段和的資訊本身不一定可以被每個節點所代表的區間的最大子段和表示,所以需要合併一些節點的資訊。include using namespace std const int maxn ...
區間最大子段和 線段樹
意思就是給你n個數,q次操作,每次改乙個值,或者詢問區間 l,r 內最大的連續子段和。線段樹維護四個東西,區間和,區間最大子段和,緊靠區間左端點的最大子段和,緊靠區間右端點的最大子段和。sum,lmax.rmax,dat,分別表示上述四種東西。sum不用說吧。對於lmax k 因為緊靠區間左端點,那...