首先我们按照长度从大到小排序,这样我们考虑宽就可以了,我们发现这样一个事情:
其中我们发现红色的点可以直接被删去,以为它们一定会被两侧的点覆盖。
于是我们的所求就是:
然后我们发现是凸的,于是我们单调栈二分就可以了,具体做法详见:[HNOI2008]玩具装箱TOY
代码实现:
//Optimize
#pragma GCC optimize("Ofast")
//Head File
#include<bits/stdc++.h>
using namespace std;
#define il inline
//Variable
#define ll long long
#define ull unsigned long long
#define db double
#define lb long double
//Debug
#define B cerr<<"Break Point"<<endl;
#define P(x) cerr<<#x<<' '<<"="<<' '<<(x)<<endl;
#define p(x) cerr<<#x<<' '<<"="<<' '<<(x)<<' ';
#define ml(x) cerr<<"Size of array is "<<x*4/1024/1024<<" MB"<<endl;
//Vector
#define vc vector
#define pub push_back
#define pob pop_back
#define vbe(x) x.begin(),x.end()
//Memset
#define ms(x) memset(x,0,sizeof(x))
#define MS(x) memset(x,0x3f3f3f3f,sizeof(x))
//Pair
#define fi first
#define se second
//File
#define fin(x) freopen(x,"r",stdin)
#define fou(x) freopen(x,"w",stdout)
void fio()
{
#ifndef ONLINE_JUDGE
freopen("sample.in","r",stdin);
freopen("sample.out","w",stdout);
#endif
}
void pti()
{
double timeuse = clock()*1000.0/CLOCKS_PER_SEC;
cerr<<"Timeuse "<<timeuse<<"ms"<<endl;
}
void end()
{
pti();
exit(0);
}
//Inf
#define INF 0x3f3f3f3f
#define LINF ((long long)(0x3f3f3f3f3f3f3f3f))
//IO
namespace io
{
const int SIZ=55;int que[SIZ],op,qr;char ch;
template<class I>
il void gi(I &w)
{
ch=getchar(),op=1,w=0;while(!isdigit(ch)){if(ch=='-') op=-1;ch=getchar();}
while(isdigit(ch)){w=w*10+ch-'0';ch=getchar();}w*=op;
}
template<class I>
il void print(I w)
{
qr=0;if(!w) putchar('0');if(w<0) putchar('-'),w=-w;while(w) que[++qr]=w%10+'0',w/=10;
while(qr) putchar(que[qr--]);
}
}
using io::gi;
using io::print;
const int N=5e4+5;
int n,m;
struct land
{
int a,b;
bool operator<(const land &x)const
{
if(a==x.a) return b>x.b;
return a>x.a;
}
};
ll f[N];
int top,stk[N],anc[N];
land c[N],t[N];
ll calc(int x,int y)
{
return f[x]+1ll*t[x+1].a*t[y].b;
}
int find(int x)
{
int l=stk[top],r=m;
while(l<=r)
{
int mid=(l+r)>>1;
if(calc(x,mid)>=calc(anc[top],mid)) l=mid+1;
else r=mid-1;
}
return l;
}
int main()
{
fio();
gi(n);
for(int i=1;i<=n;++i) gi(c[i].a),gi(c[i].b);
sort(c+1,c+n+1);
ll maxv=-1;
for(int i=1;i<=n;++i) if(c[i].b>maxv) maxv=c[i].b,t[++m]=c[i];
int cur=1;
stk[++top]=1;
for(int i=1;i<=m;++i)
{
if(i==stk[cur+1]&&cur<top) ++cur;
f[i]=calc(anc[cur],i);
while(top>0&&calc(i,stk[top])<=calc(anc[top],stk[top])) --top;
int pos=find(i);
if(pos<=m) stk[++top]=pos,anc[top]=i;
}
print(f[m]);
end();
}
来源:CSDN
作者:_DAG_
链接:https://blog.csdn.net/CaptainDAG/article/details/103721786