先考虑
a=b
a
=
b
的情况。
我们按
ai
a
i
从小到大排序,枚举
i
i
并令,那么
[i,n]
[
i
,
n
]
都是
x
x
的贡献,接下来就是找一个最大的,看成关于
i
i
的函数就是,因为自变量
i
i
单调(右移头指针),斜率此时也单调(直接在尾部插入
bi
b
i
),直接用单调队列维护凸壳即可。
但是
a≠b
a
≠
b
的情况,斜率
b
b
就不一定单调(就不能直接在尾部插入了),插入的对之前的影响就要分
<bi
<
b
i
<script type="math/tex" id="MathJax-Element-116">< b_i</script>和
≥bi
≥
b
i
两种情况了,不能直接做。
于是考虑按
b
b
的值域分块,每次插入是所在的那个块直接重构单调队列,大于的块没有影响,小于的块自变量,然后再对所有块单调队列求出最优决策取
max
max
就可以了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 150010
#define ll long long
#define ID(x) ((x-1)/B+1)
#define pll pair<ll,ll>
#define fs first
#define sc second
using namespace std;
const int B=300;
int n;
bool ex[N];
ll ans;
struct node
{
int x,y,id;
}a[N],b[N];
bool cmpx(node p,node q)
{
return p.x<q.x;
}
bool cmpy(node p,node q)
{
return p.y<q.y;
}
int read()
{
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*f;
}
struct block
{
int s,hd,tl,L,R;
pll dl[B+10];
void rebuild()
{
hd=1;tl=0;
for(int i=L,p=0;i<=R;i++)
if(ex[i])
{
pll q=make_pair(b[i].y,(ll)b[i].y*(p--)),u,v;
if(q.fs<=dl[tl].fs) continue;
for(;hd<tl;tl--)
{
u=dl[tl];v=dl[tl-1];
if((u.sc-q.sc)*(u.fs-v.fs)>(v.sc-u.sc)*(q.fs-u.fs)) break;
}
dl[++tl]=q;
}
}
ll getans()
{
pll u,v;
for(;hd<tl;hd++)
{
u=dl[hd],v=dl[hd+1];
if(u.sc+u.fs*s>v.fs*s+v.sc) break;
}
return dl[hd].fs*s+dl[hd].sc;
}
}blk[N/B+10];
int main()
{
n=read();
for(int i=1;i<=n;i++)
a[i].x=read(),a[i].y=read();
sort(a+1,a+n+1,cmpy);
for(int i=1;i<=n;i++)
a[i].id=i;
for(int i=1;i<=n;i++)
b[i]=a[i];
for(int i=1;i<=ID(n);i++)
blk[i].L=(i-1)*B+1,blk[i].R=min(n,i*B);
sort(a+1,a+n+1,cmpx);
ans=(ll)a[1].x*n;
for(int i=1;i<=n;i++)
{
ex[a[i].id]=1;
for(int j=ID(a[i].id);j;j--)
blk[j].s++;
blk[ID(a[i].id)].rebuild();
for(int j=1;j<=ID(n);j++)
ans=max(ans,blk[j].getans()+(ll)(n-i)*a[i+1].x);
}
printf("%lld",ans);
return 0;
}