CF1012 A Photo of The Sky(思考,模拟)

传送门

题意:给一个整数 n 以及 2n 个整数,要求任意排成 n 个坐标,求包含这 n 个坐标的矩形的面积的最小值

这个题应该都会想到ans=(a[n-1]-a[0])*(a[n*2-1]-a[n]),想着横坐标挨着最近,纵坐标挨着最近应该就是答案,其次最主要的是还有一种,给个数据:

4

1 1 2 3 3 3 4 11

这个如果按照这个算下是16,那么正确答案是这样的么?

正确答案是10,可以考虑这样,把最小值和最大值分别作为横坐标上的左右两边,然后在中间区间对称寻找差值最小的,可以看出剩下的点无论怎么组合绝对在这个区间内,可以自己画下。

首先取 头和尾 元素 即确定了一条边 然后再寻找另一条边 也就是遍历 a[i+n-1]-a[i] 所有值的最小值 为啥找到差值最小的 其他的点都可以放进去?

当我们选取 2 3 时 显然这两个点为(1,2) (11,3)  剩余1 3 , 3 4  首先 所以得值 都在 1~11之间 所以所有的值的横坐标都在这之内  然后再看纵坐标 若 值在 左三角 的 左侧 则左边的值为 横坐标 相对应的a[i+n-1] 为纵坐标 (因为他的值一定比右三角的值小) 同理 如果 值在 左三角 的右侧 则 右边的值为 纵坐标 (因为他的值一定比右三角的值小) 相对应的a[i+n-1] 为横坐标 (因为他的值一定比最大值小) 


所以我们可以简化成把2*n个值分成一个X集合和一个Y集合

先把a数列排序

分两种情况

1.数列的最大值和最小值在一个集合中 例如在X集合中  此时矩形的一条边为(xmax-xmin)已确知 即已经排序的数列的a[2*n-1]-a[0]  Y的边的值应该由Y确定 因为要包含在矩形里 所以要选择连续的n个点作为Y集合  此时边为【a[i],a[i+n-1]】长度为a[i+n-1]-a[i]  找出最小的a[i+n-1]-a[i]  并将这N个数放入Y集合  因为 X集合已经有最小最小值了 所以把 N个点放入Y集合 把其他的N个点(包括a[0],a[2*n-1])放入X对X边是没有影响的  此时矩形大小为   (a[2*n-1]-a[0])*min(a[i+n-1]-a[i])

2.数列的最大值和最小值不在一个集合中  此时设 X集合的最大值肯定要大于等于中间值a[n-1] Y集合的最小值肯定大于等于a[n] 此时矩形长度为 (a[n-1]-a[0])*(a[2*n-1]-a[n])


注意:long long

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#define N 0x3f3f3f3f
#define ll long long
using namespace std;
int a[201000];
int main()
{
	int n;
	while(cin>>n)
	{
	for(int i=0;i<2*n;i++)
	cin>>a[i];
	sort(a,a+2*n);
	ll aa=a[n-1]-a[0];
	ll bb=a[2*n-1]-a[n];
	ll ans=aa*bb;
	aa=a[2*n-1]-a[0];
	for(int i=1;i<n;i++)
	{
		cout<<a[n+i-1]<<" "<<a[i]<<endl;
		bb=a[n+i-1]-a[i];
		ans=min(ans,aa*bb);
	}
	cout<<ans<<endl;		
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/henucm/article/details/88579563