CF2114D Come a Little Closer

题目链接:戳这里

题目翻译

游戏区域是一个大小为 10^9 × 10^9的矩阵,其中位于第 a 行和第 b 列交叉处的单元格表示为 ( a,b )。

游戏场上有 n 个怪物,其中 i 个怪物位于( xi,yi )单元格中,其他单元格为空。一个格子中不能有超过一只怪物。

您最多可以将一只怪物移动一次到游戏场上任何一个未被其他怪物占据的格子中。

之后,您必须在场上选择个矩形;所选矩形内的所有怪物都将被消灭。你必须为所选矩形中的每个格子支付 1 枚金币。

您的任务是找出消灭所有怪物所需的最少金币数。

思路

纯思维题,不需要什么算法和数据结构。

首先维护所有点的横纵坐标最大最小值,计算出能包含所有点的矩形面积大小。

然后挨个删点,删除后对剩下的点重新计算矩形面积值,然后判断:

1.拿走的点放不进去:那么答案加上新开的一列短边

2.拿走的点能放进去:无需加入新的点

Code

#pragma G++ optimize("O3")
#include<bits/stdc++.h>
#define int long long
using namespace std;
#ifdef ONLINE_JUDGE
    const int N=200005;
#else
    const int N=2005;
#endif
int T;
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>T;
    while(T--)
    {
        int n,x[N],y[N];
        multiset<int> xcnt,ycnt;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>x[i]>>y[i];
            xcnt.insert(x[i]);
            ycnt.insert(y[i]);
        }
        int ans=0x3f3f3f3f3f3f3f3f;
        ans=min(ans,(*xcnt.rbegin()-*xcnt.begin()+1)*(*ycnt.rbegin()-*ycnt.begin()+1));
        for(int i=1;i<=n;i++)
        {
            xcnt.erase(xcnt.find(x[i]));
            ycnt.erase(ycnt.find(y[i]));
            if(!xcnt.empty()&&!ycnt.empty())
            {
                ans=min(ans,(*xcnt.rbegin()-*xcnt.begin()+1)*(*ycnt.rbegin()-*ycnt.begin()+1));
                if(ans==n-1)
                    ans+=min(*xcnt.rbegin()-*xcnt.begin()+1,*ycnt.rbegin()-*ycnt.begin()+1);
            }  
            xcnt.insert(x[i]);
            ycnt.insert(y[i]);
        }
        cout<<ans<<"\n";
    }
    return 0;
}