版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/82226155
思路:二分矩形面积。
但是2维怎么二分呢?
那么一维枚举,另一维二分。即枚举矩形的宽,二分高度。
首先把所有的点按 递增排序,然后遍历所有的点,以这个点的 坐标作为矩形的边界,然后二分高度 ,判断有多少个点在这个矩形内。
如何判断有多少个点在这个矩形内呢?
把所有点的
值离散化,每次遍历到这个点,就按
值插入树状数组。
统计的时候用树状数组统计就行了。
因为矩形的一个顶点是有4种可能的,所以要4次二分。
#include<bits/stdc++.h>
const int MAX=1e6+10;
using namespace std;
typedef long long ll;
struct Point{int x,y;}p[MAX];
int cmp1(const Point&p,const Point&q){return p.x<q.x;}
int BIT[MAX];
void add(int x,int n){while(x<=n){BIT[x]++;x+=x&(-x);}}
int ask(int x){int tot=0;while(x){tot+=BIT[x];x-=x&(-x);}return tot;}
vector<int>v;
int id(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
int main()
{
int M,n;
while(scanf("%d%d",&M,&n)!=EOF)
{
for(int i=1;i<=n;i++)scanf("%d%d",&p[i].x,&p[i].y);
if(n%2)
{
puts("-1");
continue;
}
sort(p+1,p+n+1,cmp1);
v.clear();
for(int i=1;i<=n;i++)v.push_back(p[i].y); //将y值离散化
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
ll ans=6e18;
for(int i=1;i<=n;i++)BIT[i]=0;
for(int i=1;i<=n;i++)
{
add(id(p[i].y),n);
while(i+1<=n&&p[i+1].x==p[i].x)
{
i++;
add(id(p[i].y),n);
}
int L=1,R=v.size();
while(R>=L) //以左下角为矩形一个顶点二分
{
int m=(L+R)/2;
if(ask(m)>=n/2)
{
R=m-1;
if(ask(m)==n/2)ans=min(ans,1ll*(v[m-1]+1)*(p[i].x+1));
}
else L=m+1;
}
L=1,R=v.size();
while(R>=L) //以左上角为矩形一个顶点二分
{
int m=(L+R)/2;
if(ask(n)-ask(m-1)>=n/2)
{
L=m+1;
if(ask(n)-ask(m-1)==n/2)ans=min(ans,1ll*(M-v[m-1])*(p[i].x+1));
}
else R=m-1;
}
}
for(int i=1;i<=n;i++)BIT[i]=0;
for(int i=n;i>=1;i--)
{
add(id(p[i].y),n);
while(i-1>=1&&p[i-1].x==p[i].x)
{
i--;
add(id(p[i].y),n);
}
int L=1,R=v.size();
while(R>=L) //以右下角为矩形一个顶点二分
{
int m=(L+R)/2;
if(ask(m)>=n/2)
{
R=m-1;
if(ask(m)==n/2)ans=min(ans,1ll*(v[m-1]+1)*(M-p[i].x));
}
else L=m+1;
}
L=1,R=v.size();
while(R>=L) //以右上角为矩形一个顶点二分
{
int m=(L+R)/2;
if(ask(n)-ask(m-1)>=n/2)
{
L=m+1;
if(ask(n)-ask(m-1)==n/2)ans=min(ans,1ll*(M-v[m-1])*(M-p[i].x));
}
else R=m-1;
}
}
if(ans>=5e18)puts("-1");
else printf("%lld\n",ans);
}
return 0;
}