zoukankan      html  css  js  c++  java
  • [USACO08MAR]土地征用Land Acquisition

    题面在这里

    题意

    约翰准备扩大他的农场,眼前他正在考虑购买N块长方形的土地。
    如果约翰单买一块土地,价格就是土地的面积,但他可以选择并购一组土地,
    并购的价格为这些土地中最大的长乘以最大的宽。
    给定每份土地的尺寸,请你帮助他计算购买所有土地所需的最小费用。

    数据范围

    [1 le N le 50000,1 le width_i,length_ile 10^6 ]

    sol

    我们发现,如果一块土地被另一块土地所包含(即长和宽都比另一块土地小),
    那么只需购买那另一块土地即可,于是我们可以据此筛掉其他的土地,
    只剩下一些长度递减,宽度递增的土地

    然后我们猜想FJ每次购买的一组土地肯定是这个序列连续的一段
    (假设某种最优方案中购买的土地不是一段,那么将中间的部分补上显然不会更劣)

    于是就变成了经典的序列分段问题,
    (f[i])表示购买前(i)块土地所需的最小代价,我们有

    [f[i]=min_{j=0}^{i-1}(f[j]+length[j] imes width[i]) ]

    斜率优化插点((-length[j],f[j])),按照递增的(k=width[i])处理即可

    代码

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    using namespace std;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    const dd eps=1e-10;
    const int mod=1e8;
    const int N=50010;
    il ll read(){
    	RG ll data=0,w=1;RG char ch=getchar();
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
    	return data*w;
    }
    
    il void file(){
    	freopen(".in","r",stdin);
    	freopen(".out","w",stdout);
    }
    
    int n,m;ll f[N];
    struct area{ll a,b;}s[N];
    bool cmp(area x,area y){
    	if(x.a==y.a)return x.b>y.b;
    	else return x.a>y.a;
    }
    
    struct node{ll x,y;}Q[N];ll L=1,R;
    il void insert(node q){
    	while(L<R&&(Q[R].y-Q[R-1].y)*(q.x-Q[R].x)>(q.y-Q[R].y)*(Q[R].x-Q[R-1].x))R--;
    	Q[++R]=q;
    }
    il ll query(ll k){
    	while(L<R&&k*(Q[L+1].x-Q[L].x)>Q[L+1].y-Q[L].y)L++;
    	return Q[L].y-Q[L].x*k;
    }
    
    int main()
    {
    	n=read();
    	for(RG int i=1;i<=n;i++)s[i].a=read(),s[i].b=read();
    	sort(s+1,s+n+1,cmp);
    	for(RG int i=1;i<=n;i++)
    		if(!m||s[i].a<s[m].a&&s[i].b>s[m].b)s[++m]=s[i];
    	insert((node){-s[1].a,0});
    	for(RG int i=1;i<=m;i++){
    		f[i]=query(s[i].b);
    		insert((node){-s[i+1].a,f[i]});
    	}
    	printf("%lld
    ",f[m]);
    	return 0;
    }
    
    
  • 相关阅读:
    linux(centos6.9) 安装mongoDB
    vue $refs
    vue $emit的使用方式
    docker上部署一个项目常用命令
    Nginx之Location匹配规则
    Github Packages和Github Actions实践之CI/CD
    消息中间件选型分析:从 Kafka 与 RabbitMQ 的对比看全局
    发布Jar包到maven中央仓库
    一些小Tip
    有风格的程序员,写有风格的代码
  • 原文地址:https://www.cnblogs.com/cjfdf/p/8645621.html
Copyright © 2011-2022 走看看