1. 程式人生 > 其它 >P2900 [USACO08MAR]土地購買Land Acquisition G

P2900 [USACO08MAR]土地購買Land Acquisition G

技術標籤:P2900USACO08MARLand土地購買

文章目錄

R e s u l t Result Result

...


H y p e r l i n k Hyperlink Hyperlink

https://www.luogu.com.cn/problem/P2900


D e s c r i p t i o n Description Description

n n n塊土地,第 i i i塊土地的長為 x i x_i xi,寬為 y i y_i yi ,現需將這些土地分成若干組,分成一組將產生這一組內長的最大值 × \times ×寬的最大值的代價,試確定一種分組方案,使得總代價最小

資料範圍: n ≤ 5 × 1 0 4 , x i , y i ≤ 1 0 6 n\leq 5\times 10^4,x_i,y_i\leq 10^6 n5×104,xi,yi106


S o l u t i o n Solution
Solution

將每個土地的長和寬抽象的看做是一個點 ( x , y ) (x,y) (x,y),注意到如果存在兩個點 A ( x , y ) , B ( x ‘ , y ‘ ) A(x,y),B(x^`,y^`) A(x,y),B(x,y)滿足 x ≤ x ‘ , y ≤ y ‘ x\leq x^`,y\leq y^` xx,yy,則 A A A這個點是可以捨棄的,因為顯然當且僅當把它和 B B B劃分到一起答案會更優。

如果我們把所有矩形按照 x x x為第一關鍵字升序排序,剩下來的點在第一象限中就構成了階梯型。

f i f_i fi表示劃分到第 i i i個矩形的最優代價

顯然列舉 j j j表示把 [ j + 1 ∼ i ] [j+1\sim i] [j+1i]劃分到一起得到方程 f i = m i n { f j + y j + 1 × x i } f_i=min\{f_j+y_{j+1}\times x_i\} fi=min{fj+yj+1×xi} x x x遞增,所以最大值在 i i i取, y y y遞減,所以最大值在 j + 1 j+1 j+1取】

可以證明或打表發現 f j f_j fj後面那坨滿足四邊形不等式,即 f f f具有決策單調性

如此,我們只需考慮每個決策對後續轉移的影響,然後二分出決策的賺一點即可

時間複雜度: O ( n log ⁡ 2 n ) O(n\log_2 n) O(nlog2n)


C o d e Code Code

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define LL long long
#define N 50010
using namespace std;int n,m,tl,hd,maxl;
struct node{LL x,y;}a[N];
struct note{int l,r,x;}que[N];
inline bool cmp(node x,node y){return x.x<y.x||x.x==y.x&&x.y>y.y;}
LL f[N];
inline LL read()
{
	char c;LL d=1,f=0;
	while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
inline LL Cost(int i,int j){return f[i]+a[i+1].y*a[j].x;}
inline int findx(int i)
{
	int L=que[tl].l,R=que[tl].r,mid;
	while(L<=R)
	{
		mid=L+R>>1;
		if(Cost(i,mid)<Cost(que[tl].x,mid)) R=mid-1;else L=mid+1;
	}
	return L;
}
signed main()
{
	n=read();
	for(register int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();
	sort(a+1,a+1+n,cmp);
	for(register int i=1;i<=n;i++)
	{
		while(m&&a[m].y<=a[i].y) m--;
		a[++m]=a[i];
	}
	que[hd=tl=1]=(note){1,m,0};
	for(register int i=1;i<=m;i++)
	{
		while(hd<=tl&&que[hd].r<i) hd++;
		f[i]=Cost(que[hd].x,i);
		while(hd<=tl&&i<que[tl].l&&Cost(i,que[tl].l)<Cost(que[tl].x,que[tl].l)) tl--;
		int u=findx(i);que[tl].r=u-1;
		if(u<=m) que[++tl]=(note){u,m,i};
	}
	printf("%lld",f[m]);
}