BZOJ4951 Wf2017Money for Nothing(决策单调性)

  按时间排序,显然可能存在于答案中的公司价格应该单调递减。然后就可以大胆猜想感性证明其有决策单调性。具体地,设f(i,j)表示第i个消费公司和第j个生产公司搭配的获利,f(i,j)=(ti-tj)*(ci-cj),即证若f(i,j)>f(i,k) (k<j),则f(i+1,j)>f(i+1,k)。(ti-tj)*(ci-cj)>(ti-tk)*(ci-ck)→tjcj-ticj-tjci>tkck-tick-tkci→tjcj-tkck>ti(cj-ck)+ci(tj-tk) (cj<ck,tj>tk),又由ti+1>ti,ci+1<ci,得tjcj-tkck>ti+1(cj-ck)+ci+1(tj-tk),再倒推回去即得原式。由上面的推导可以发现显然不会存在于答案中的公司仍会对决策单调性产生影响,开始时得去掉。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 500010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,L[N],R[N],id[N],top;
ll ans;
struct data{int x,y;
}a[N],b[N],c[N];
bool cmp(const data&a,const data&b)
{
    return a.x<b.x;
}
ll calc(int x,int y){if (b[y].x<a[x].x) return 0;return 1ll*(b[y].x-a[x].x)*(b[y].y-a[x].y);}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj4951.in","r",stdin);
    freopen("bzoj4951.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read(),m=read();
    for (int i=1;i<=n;i++) a[i].y=read(),a[i].x=read();
    for (int i=1;i<=m;i++) b[i].y=read(),b[i].x=read();
    sort(a+1,a+n+1,cmp),sort(b+1,b+m+1,cmp);
    int t=0,mn=1000000001;
    for (int i=1;i<=n;i++) if (a[i].y<mn) c[++t]=a[i],mn=a[i].y;
    n=t;for (int i=1;i<=n;i++) a[i]=c[i];
    t=0;int mx=0;
    for (int i=m;i>=1;i--) if (b[i].y>mx) c[++t]=b[i],mx=b[i].y;
    m=t;for (int i=1;i<=m;i++) b[i]=c[i];reverse(b+1,b+m+1);
    for (int i=1;i<=n;i++)
    {
        while (top&&calc(i,L[top])>calc(id[top],L[top])) top--;
        int l=L[top],r=R[top],x=R[top]+1;
        while (l<=r)
        {
            int mid=l+r>>1;
            if (calc(i,mid)>calc(id[top],mid)) x=mid,r=mid-1;
            else l=mid+1;
        }
        R[top]=x-1;
        if (x<=m) top++,id[top]=i,L[top]=x,R[top]=m;
    }
    for (int i=1;i<=top;i++)
        for (int j=L[i];j<=R[i];j++)
        ans=max(ans,calc(id[i],j));
    cout<<ans;
    return 0;
}

 

posted @ 2018-12-02 15:50  Gloid  阅读(252)  评论(0编辑  收藏  举报