zjnu1189 土地租用(完整版)

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 77   Accepted: 10

Description

随着YYHS的OI集训队人数急剧增加,原有的小机房已经容纳不了数量庞大的队员。
于是史老师决定租用一些实验室机位供队员们训练,他正在考虑为N (1 <= N <= 50,000)位队员租用机位。实验室管理员根据要求给出了N个机位的长和宽,每个机位的长宽满足(1 <= 宽 <= 1,000,000; 1 <= 长 <= 1,000,000).
而机位的租用价格是它的面积,实验室管理员也提出,可以同时租用多个机位. 租用这一组机位的价格是它们最大的长乘以它们最大的宽, 但是机位的长宽不能交换. 如果想租下一个3x5的机位和一个5x3的机位,则他需要付5x5=25.
于是问题出现了,史老师希望租下所有的机位,但是他发现分组来租这些机位可以节省经费. 他需要你帮助他找到最小的经费.
 

Input

* 第1行: 一个数: N
* 第2..N+1行: 每行包含两个数,分别为机位的长和宽
 

Output

* 第一行: 最小的可行费用.

Sample Input

  
  
  
  
4 100 1 15 15 20 5 1 100

Sample Output

  
  
  
  

500

这题如果是用n*n的dp,会超时,所以要用斜率优化,和hdu3669差不多的思路。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 999999999999999999
#define maxn 50050
struct node{
    ll w,h;
}a[maxn],b[maxn];

bool cmp(node a,node b){
    if(a.w==b.w)return a.h>b.h;
    return a.w>b.w;
}
ll dp[maxn];
ll q[1111111];
ll getup(int x)
{
    return dp[x];
}
ll getdown(int x)
{
    return -b[x+1].w;

}


int main()
{
    int n,m,i,j,tot,k;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=n;i++){
            scanf("%d%d",&a[i].w,&a[i].h);
        }
        sort(a+1,a+1+n,cmp);
        tot=1;b[tot].w=a[1].w;b[tot].h=a[1].h;
        for(i=2;i<=n;i++){
            if(b[tot].h>=a[i].h)continue;
            tot++;b[tot].w=a[i].w;b[tot].h=a[i].h;

        }
        int front,rear;
        front=1;rear=1;
        q[rear]=0;
        for(i=1;i<=tot;i++){
            //dp[i]=b[1].w*b[i].h;  这里如果前面不把0加入队列的话,那么这句话要加上。
            while(front<rear && getup(q[front+1])-getup(q[front])<=b[i].h*(getdown(q[front+1])-getdown(q[front]) )  ){
                front++;
            }
            k=q[front];
            dp[i]=dp[k]+b[k+1].w*b[i].h;
            //dp[i]=min(dp[i],dp[k]+b[k+1].w*b[i].h);
            while(front<rear && ( getup(q[rear])-getup(q[rear-1] ) )*(getdown(i)-getdown(q[rear] ))>=( getup(i)-getup(q[rear] ) )*(getdown(q[rear])-getdown(q[rear-1] ))   ){
                rear--;
            }
            rear++;
            q[rear]=i;

        }
        printf("%lld\n",dp[tot]);
    }
    return 0;
}


你可能感兴趣的:(斜率优化,区间DP)