Codeforces-Gym 101505G:Orchard Division(二分+树状数组)

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/82226155

传送门是什么东西?

思路:二分矩形面积。

但是2维怎么二分呢?

那么一维枚举,另一维二分。即枚举矩形的宽,二分高度。

首先把所有的点按 x 递增排序,然后遍历所有的点,以这个点的 x 坐标作为矩形的边界,然后二分高度 h ,判断有多少个点在这个矩形内。

如何判断有多少个点在这个矩形内呢?

把所有点的 y 值离散化,每次遍历到这个点,就按 y 值插入树状数组。
统计的时候用树状数组统计就行了。

因为矩形的一个顶点是有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;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/82226155