首先,可以通过将所有$x_{i}=0$都选择第1类,其余选第2类,构造出一个以$(0,0)$和$(1,h)$为左下角和右上角的矩形,答案即为$2h+2$,类似地还可以构造出$2w+2$
若最终的矩形不包含与$x=frac{w}{2}$或$y=frac{h}{2}$,那么意味着答案不超过$w+h$,而上面的构造得到了答案$2max(w,h)+2$的下限,因此一定不优
接下来,我们分别考虑与$x=frac{w}{2}$有交和与$y=frac{h}{2}$有交的答案,取max即可
以$y=frac{h}{2}$为例,暴力枚举右端点的$x$(记作$x_{i}$),即找到$j$,并最大化$x_{i}-x_{j}+Delta y_{j+1,i-1}$(其中$Delta y_{i,j}$指对应的最小的$y$坐标差,即$min_{ile kle j,y_{k}>frac{h}{2}}y_{k}-max_{ile kle j,y_{k}le frac{h}{2}}y_{k}$)
(关于$Delta y_{i,j}$中若存在$ile kle j$且$y_{k}=frac{h}{2}$,看上去会有两种可能,但一定不优,任取即可)
$x_{i}$是关于$i$的常数,即要求最大化$Delta y_{j+1,i-1}-x_{j}$,注意到每一次增加$i$也就是对$Delta y_{j+1,i-1}$执行区间修改,修改的区间个数恰好与单调栈弹出数相同,用线段树来维护$Delta y_{j+1,i-1}-x_{j}$最大值即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 300005 4 #define oo 0x3f3f3f3f 5 #define L (k<<1) 6 #define R (L+1) 7 #define mid (l+r>>1) 8 #define fi first 9 #define se second 10 stack<int>st[2]; 11 pair<int,int>a[N]; 12 int n,w,h,ans,f[N<<2],tag[N<<2]; 13 void upd(int k,int x){ 14 tag[k]+=x; 15 f[k]+=x; 16 } 17 void down(int k){ 18 upd(L,tag[k]); 19 upd(R,tag[k]); 20 tag[k]=0; 21 } 22 void update(int k,int l,int r,int x,int y,int z){ 23 if ((l>y)||(x>r))return; 24 if ((x<=l)&&(r<=y)){ 25 upd(k,z); 26 return; 27 } 28 down(k); 29 update(L,l,mid,x,y,z); 30 update(R,mid+1,r,x,y,z); 31 f[k]=max(f[L],f[R]); 32 } 33 void calc(){ 34 sort(a+1,a+n+1); 35 while (!st[0].empty())st[0].pop(); 36 st[0].push(0); 37 while (!st[1].empty())st[1].pop(); 38 st[1].push(0); 39 memset(tag,0,sizeof(tag)); 40 memset(f,0,sizeof(f)); 41 upd(1,-oo); 42 int hh=h/2; 43 for(int i=1;i<=n;i++){ 44 update(1,1,n,i,i,oo+h-a[i-1].fi); 45 ans=max(ans,a[i].fi+f[1]); 46 int p=(a[i].se>hh),las=i,x=abs(a[i].se-hh)-abs(p*h-hh); 47 while (1){ 48 update(1,1,n,st[p].top()+1,las,x); 49 las=st[p].top(); 50 x=abs(a[i].se-hh)-abs(a[las].se-hh); 51 if ((!las)||(x>0))break; 52 st[p].pop(); 53 } 54 st[p].push(i); 55 } 56 ans=max(ans,w+max(f[1],h-a[n].fi)); 57 } 58 int main(){ 59 scanf("%d%d%d",&w,&h,&n); 60 for(int i=1;i<=n;i++)scanf("%d%d",&a[i].fi,&a[i].se); 61 calc(); 62 swap(w,h); 63 for(int i=1;i<=n;i++)swap(a[i].fi,a[i].se); 64 calc(); 65 printf("%d",2*ans); 66 }