【gdgzezoi】Problem A: 小球染色

Description

有 n 个袋子,每个袋子里装着两个白球。i 号袋子里的两个白球上面分别写着 xi,yi 两个数字。现在给球染色,每个袋子里的两个球要染成一红一蓝。染色后把 2n 个球都拿出来,定义:

  • Rmax 为红色的球上最大的数字
  • Rmin 为红色的球上最小的数字
  • Bmax 为蓝色的球上最大的数字
  • Bmin 为蓝色的球上最小的数字

求 (Rmax−Rmin)(Bmax−Bmin) 的最小值。
Input
第一行是一个整数 n (1≤n≤2×105) ,接下来是 n 行,每行两个数 xi,yi (1≤xi,yi≤109) ,表示第 i 个袋子中的两个球上的数字。
Output
输出一行一个整数,代表 (Rmax−Rmin)(Bmax−Bmin) 的最小值 。
Sample Input
sample input 1:
3
1 2
3 4
5 6

sample input 2:
3
1010 10
1000 1
20 1020

sample input 3:
2
1 1
1000000000 1000000000
Sample Output
sample output 1:
15

sample output 2:
380

sample output 3:
999999998000000001
HINT
样例 1 最优方案为 x1,x2,y3 染红 y2,y2,x3 染蓝

思路

考虑全局最大值和最小值,要么同时作为某个颜色的最大/最小值,要么分别是两个不同颜色的最大/最小值。后者比较好办,显然应该所有点较大的那个值染成同一个颜色,较小的染成另一个颜色。

如果全局最大最小值是同一个颜色就比较麻烦了。不妨设这两个值都染成了红色。这时,其他的所有值都可以染成红色,不会超出范围。所以问题转化成剩下的点每个点选一个值染成蓝色,使得蓝色的最大值减最小值最小。

代码

#include<bits/stdc++.h>
#define N 220077
#define ll long long
using namespace std;
struct arr
{
    ll x,y;
}p[N];
ll n,Rmax,Rmin,Lmax,Lmin,r,l,Max,Min;
bool operator < (arr a,arr b)
{
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.x;
}
ll solve1()
{
    Max=p[1].y,Min=p[1].x;r=1;l=1;
    for(int i=2;i<=n;i++)
    {
        if(p[i].x<Min)Min=p[i].x,l=i;
        if(p[i].y>Max)Max=p[i].y,r=i;
    }
    Rmax=Max;Lmin=Min;
    Rmin=p[l].y;Lmax=p[r].x;
    for(int i=1;i<=n;i++)
    {
        Rmin=min(Rmin,p[i].y);
        Lmax=max(Lmax,p[i].x);
    }
    return (ll)(Rmax-Rmin)*(Lmax-Lmin);
}
ll solve2(){
    Lmax=Max;
    Lmin=Min;
    Rmax=max(p[n].x,p[1].y);
    ll k=p[1].y;
    Rmin=min(p[1].y,p[2].x);
    ll ans=Rmax-Rmin;
    for(int i=2;i<=n-1;i++){
        k=min(k,p[i].y);
        Rmax=max(p[i].y,Rmax);
        Rmin=min(k,p[i+1].x);
        if(Rmax-Rmin<ans)ans=Rmax-Rmin;
    }
    return (ll)ans*(Lmax-Lmin);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&p[i].x,&p[i].y);
        if(p[i].x>p[i].y)swap(p[i].x,p[i].y);
    }
    sort(p+1,p+n+1);
    ll ans=solve1();
    if(r!=l)ans=min(ans,solve2());
    printf("%lld",ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值