简要题意:
你有一个 W × H W \times H W×H 的矩形,中间一些位置上有树。请你求一个空矩形(允许边界有树),最大化周长。
W , H ≤ 1 e 8 W,H\leq 1e8 W,H≤1e8,树的个数 ≤ 3 e 5 \leq 3e5 ≤3e5
题解:
容易注意到答案至少是 2 × max ( W , H ) + 2 2\times \max(W,H)+2 2×max(W,H)+2。因为不管树怎么排,宽度为 1 1 1 的矩形永远都是可行的。于是容易注意到答案矩形必然穿过横向的中线或纵向的中线。
直接单调栈维护一下从中线向两边看到的情况,发现视角在向下移的时候对应栈中的区间加,同时需要维护一下坐标差的最大值,随便用一个数据结构即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}
}using namespace IO;
using std::cerr;
using std::cout;
cs int N=3e5+7;
int n,W,H,ans;
struct pt{int x,y;}p[N];
namespace SGT{
cs int N=::N<<2|7;
int mx[N],tg[N];
#define lc u<<1
#define rc lc|1
void build(int u,int l,int r){
tg[u]=0,mx[u]=-p[l].y;if(l==r)return ;
int mid=(l+r)>>1;build(lc,l,mid);build(rc,mid+1,r);
}
void add(int u,int l,int r,int ql,int qr,int vl){
if(qr<l||r<ql)return ;
if(ql<=l&&r<=qr)
{tg[u]+=vl,mx[u]+=vl;return;}
int mid=(l+r)>>1;
if(ql<=mid)add(lc,l,mid,ql,qr,vl);
if(mid<qr)add(rc,mid+1,r,ql,qr,vl);
mx[u]=std::max(mx[lc],mx[rc])+tg[u];
}
inline void add(int l,int r,int vl){add(1,1,n,l,r,vl);}
#undef lc
#undef rc
}
int s1[N],t1,s2[N],t2;
void calc(){
std::sort(p+1,p+n+1,[](cs pt &a,cs pt &b){
return a.y<b.y||(a.y==b.y&&a.x<b.x);
});SGT::build(1,1,n);t1=t2=0;
for(int re i=1;i<=n;++i){
if(i>1)SGT::add(i-1,i-1,W);
ans=std::max(ans,(p[i].y+SGT::mx[1]));
if(p[i].x<=W/2){
SGT::add(s1[t1],i-1,-p[i].x);
while(t1&&p[s1[t1]].x<p[i].x)
{SGT::add(s1[t1-1],s1[t1]-1,p[s1[t1]].x-p[i].x);--t1;}
s1[++t1]=i;
}else {
SGT::add(s2[t2],i-1,p[i].x-W);
while(t2&&p[s2[t2]].x>p[i].x)
{SGT::add(s2[t2-1],s2[t2]-1,p[i].x-p[s2[t2]].x);--t2;}
s2[++t2]=i;
}
}
}
void Main(){
W=gi(),H=gi(),n=gi();
for(int re i=1;i<=n;++i)p[i].x=gi(),p[i].y=gi();
p[++n]={0,0};p[++n]={W,H};calc();
for(int re i=1;i<=n;++i)std::swap(p[i].x,p[i].y);
std::swap(W,H);calc();cout<<ans*2<<"\n";
}
void file(){
#ifdef zxyoi
freopen("farm.in","r",stdin);
#endif
}
signed main(){file();Main();return 0;}