BZOJ 1597 土地购买(斜率优化DP)
如果有一块土地的长和宽都小于另一块土地的长和宽,显然这块土地属于“赠送土地”。
我们可以排序一下将这些赠送土地全部忽略掉,一定不会影响到答案。
那么剩下的土地就是长递减,宽递增的。令dp[i]表示购买前i个土地的最小代价。
显然有dp[i]=min(dp[j]+ku[i]*ch[j+1]).(j<i)。 其中ku[i]表示第i个土地的宽,ch[i]表示第i个土地的长。
这个式子得用斜率优化一下。很normal,推出式子就解决了。
# include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath> # include <algorithm> using namespace std; # define lowbit(x) ((x)&(-x)) # define pi 3.1415926535 # define eps 1e-9 # define MOD 100000007 # define INF 1000000000 # define mem(a,b) memset(a,b,sizeof(a)) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define FO(i,a,n) for(int i=a; i<n; ++i) # define bug puts("H"); # define lch p<<1,l,mid # define rch p<<1|1,mid+1,r # define mp make_pair # define pb push_back typedef pair<int,int> PII; typedef vector<int> VI; # pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; int Scan() { int res=0, flag=0; char ch; if((ch=getchar())=='-') flag=1; else if(ch>='0'&&ch<='9') res=ch-'0'; while((ch=getchar())>='0'&&ch<='9') res=res*10+(ch-'0'); return flag?-res:res; } void Out(int a) { if(a<0) {putchar('-'); a=-a;} if(a>=10) Out(a/10); putchar(a%10+'0'); } const int N=50005; //Code begin... struct Node{int x, y;}node[N]; LL dp[N]; int que[N], head=-1, tail; bool comp(Node a, Node b){ if (a.x==b.x) return a.y>b.y; return a.x>b.x; } bool check(int x, int y, int z){return dp[x]-dp[y]<=(LL)-node[z].y*(node[x+1].x-node[y+1].x);} bool sol(int x, int y, int z){ return (dp[x]-dp[y])*(node[y+1].x-node[z+1].x)>=(dp[y]-dp[z])*(node[x+1].x-node[y+1].x); } int main () { int n; scanf("%d",&n); FOR(i,1,n) scanf("%d%d",&node[i].x,&node[i].y); sort(node+1,node+n+1,comp); int pos=1; FOR(i,2,n) if (node[pos].y<node[i].y) node[++pos].x=node[i].x, node[pos].y=node[i].y; que[++head]=0; FOR(i,1,pos) { while (head>tail&&check(que[tail+1],que[tail],i)) ++tail; int v=que[tail]; dp[i]=(LL)node[i].y*node[v+1].x+dp[v]; while (head>tail&&sol(i,que[head],que[head-1])) --head; que[++head]=i; } printf("%lld\n",dp[pos]); return 0; }