P2900 [USACO08MAR]土地徵用Land Acquisition (斜率優化dp)

題目描述

Farmer John is considering buying more land for the farm and has his eye on N (1 <= N <= 50,000) additional rectangular plots, each with integer dimensions (1 <= width_i <= 1,000,000; 1 <= length_i <= 1,000,000).

If FJ wants to buy a single piece of land, the cost is $1/square unit, but savings are available for large purchases. He can buy any number of plots of land for a price in dollars that is the width of the widest plot times the length of the longest plot. Of course, land plots cannot be rotated, i.e., if Farmer John buys a 3x5 plot and a 5x3 plot in a group, he will pay 5x5=25.

FJ wants to grow his farm as much as possible and desires all the plots of land. Being both clever and frugal, it dawns on him that he can purchase the land in successive groups, cleverly minimizing the total cost by grouping various plots that have advantageous width or length values.

Given the number of plots for sale and the dimensions of each, determine the minimum amount for which Farmer John can purchase all

輸入格式

* Line 1: A single integer: N

* Lines 2..N+1: Line i+1 describes plot i with two space-separated integers: width_i and length_i

輸出格式

* Line 1: The minimum amount necessary to buy all the plots.

輸入輸出樣例


100 1 
15 15 
20 5 
1 100 
 

500

說明/提示

There are four plots for sale with dimensions as shown.

The first group contains a 100x1 plot and costs 100. The next group contains a 1x100 plot and costs 100. The last group contains both the 20x5 plot and the 15x15 plot and costs 300. The total cost is 500, which is minimal.

題意:有n塊矩形土地,單買一塊土地的花費等於該土地的面積,但是如果我們要買下一組土地,花費的錢等於該組土地中最大的長乘以最大的寬,clf(土豪)想要想買下所有土地,問至少需要多少錢?

題解:存在一些土地的長和寬都小於某塊土地,所以我們可以優先去掉這些白給的土地,剩下的土地我們排序可以發現,當土地的長遞增時,土地的寬必定遞減。就很容易寫出一個dp方程:

dp[i] = min\left \{ dp[j] + a[i].x * a[j+1].y \right \}  ,其中dp[i]表示前i塊土地的最小花費,複雜度O(n^{2})

化爲:dp[j] =- a[i].x * a[j+1].y + dp[i],斜率優化一下就OK了,複雜度O(n)

//#include<bits/stdc++.h>
//#include<unordered_map>
//#include<unordered_set>
#include<iostream>
#include<sstream>
#include<iterator>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<vector>
#include<bitset>
#include<climits>
#include<queue>
#include<iomanip>
#include<cmath>
#include<stack>
#include<map>
#include<ctime>
#include<new>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define MT(a, b) memset(a,b,sizeof(a))
#define lson l, mid, node<<1
#define rson mid + 1, r, node<<1|1
const int INF  =  0x3f3f3f3f;
const int O    =  1e6;
const int mod  =  1e9+7;
const int maxn =  2e5 +5;
const double PI  =  acos(-1.0);
const double E   =  2.718281828459;
const double eps = 1e-8;

struct dd {
    LL x,  y;
    bool friend operator < (dd a, dd b) {
        return a.x == b.x ? a.y < b.y : a.x < b.x;
    }
}a[maxn], b[maxn];

LL dp[maxn];

double get_k(int i, int j){
    return double(dp[j] - dp[i]) / double(a[j+1].y - a[i+1].y);
}

int main(){
    int n; cin >> n;
    for(int i=0; i<n; i++) scanf("%lld%lld", &a[i].x, &a[i].y);
    sort(a, a + n);
    int cnt =0 ; b[cnt ++] = a[n-1];
    for(int i = n-2; i>=0; i--) {
        if(a[i].y <= b[cnt-1].y) continue;
        b[cnt ++] = a[i];
    }
    for(int i=0; i<cnt; i++) a[i+1] = b[cnt-i-1];
    int q[maxn], l = 0, r = 0; q[r ++] = 0;
        for(int i=1; i<=cnt; i++) {
        while(l < r - 1 && -a[i].x <= get_k(q[l], q[l+1])) l ++;
        dp[i] = dp[q[l]] + a[i].x * a[q[l]+1].y;
        while(l < r - 1 && get_k(i, q[r-1]) >= get_k(q[r-1], q[r-2])) r --;
        q[r ++] = i;
    }
    cout << dp[cnt] <<endl;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章