bzoj4951 [Wf2017]Money for Nothing

题目描述

题解:

答案显然是$max((q-p)*(e-d))$

依然先贪心。

对于工厂,我们倾向于$pi<pj,di<dj$的;

对于买家,我们倾向于$qi>qj,ei>ej$的。

于是将一定不是最优解的工厂和买家划掉。

然后我们发现这个东西是满足决策单调性的。

问我怎么证?画一个二维坐标系,然后将选中的点都画上,然后就理性易证了。

最后分治。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 500050
#define ll long long
inline ll rd()
{
    ll f=1,c=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
    return f*c;
}
int n0,m0,n,m;
struct Pair
{
    ll x,y;
    Pair(){}
    Pair(ll x,ll y):x(x),y(y){}
};
bool cmp1(Pair a,Pair b)
{
    if(a.x!=b.x)return a.x<b.x;
    return a.y<b.y;
}
bool cmp2(Pair a,Pair b)
{
    if(a.x!=b.x)return a.x<b.x;
    return a.y>b.y;
}
Pair a0[N],b0[N],a[N],b[N];
ll ans = 0;
void divi(int l1,int r1,int l2,int r2)
{
    if(l1>r1||l2>r2)return ;
    if(l1==r1)
    {
        for(int i=l2;i<=r2;i++)
            if(b[i].x>a[l1].x)ans = max(ans,(b[i].x-a[l1].x)*(b[i].y-a[l1].y));
        return ;
    }
    if(l2==r2)
    {
        for(int i=l1;i<=r1;i++)
            if(b[l2].x>a[i].x)ans = max(ans,(b[l2].x-a[i].x)*(b[l2].y-a[i].y));
        return ;
    }
    int mid = (l2+r2)>>1;
    int pos=l1;
    ll max_val=-0x3f3f3f3f3f3f3f3fll;
    for(int i=l1;i<=r1;i++)
    {
        if(b[mid].x<=a[i].x&&b[mid].y<=a[i].y)continue;
        if((b[mid].x-a[i].x)*(b[mid].y-a[i].y)>max_val)
        {
            pos = i;
            max_val=(b[mid].x-a[i].x)*(b[mid].y-a[i].y);
        }
    }
    ans=max(ans,max_val);
    divi(l1,pos,l2,mid-1);
    divi(pos,r1,mid+1,r2);
}
int main()
{
//  freopen("33.in","r",stdin);
    n0 = rd(),m0 = rd();
    for(int i=1;i<=n0;i++)
        a0[i].x = rd(),a0[i].y = rd();
    for(int i=1;i<=m0;i++)
        b0[i].x = rd(),b0[i].y = rd();
    sort(a0+1,a0+1+n0,cmp1);
    sort(b0+1,b0+1+m0,cmp2);
    ll lim = 0x3f3f3f3f3f3f3f3fll;
    for(int i=1;i<=n0;i++)
        if(a0[i].y<lim)
        {
            a[++n]=a0[i];
            lim = a0[i].y;
        }
    for(int i=1;i<=m0;i++)
    {
        while(m&&b[m].y<=b0[i].y)m--;
        b[++m]=b0[i];
    }
    divi(1,n,1,m);
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2019-01-04 09:52  LiGuanlin  阅读(297)  评论(0编辑  收藏  举报