「ARC 063F」Snuke's Coloring 2

给定一个 W×HW\times H 的二维平面,初始均为白色,有 nn 个关键点 (xi,yi)(x_{i},y_{i}) ,对于每一个关键点选择一个方向,并将该方向上的所有网格涂成黑色。易得操作后白色部分一定是一个矩形,请最大化矩形周长。

avatar

Constraints

0n21050 \leq n \leq 2 \cdot 10^51w,h1081 \leq w,h \leq 10^8

Solution

观察可以得到一个性质,答案矩形一定会经过直线 x=W2x=\frac{W}{2}y=H2y=\frac{H}{2} 。两种情况可以用相同的方式处理出答案。

将坐标离散化后,枚举矩形的上下边界,可以直接计算出矩形的左右边界。考虑用线段树进行优化。左右各开一个单调栈,在维护单调栈时在线段树上进行区间加减即可。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
#define lc(x) x<<1
#define rc(x) x<<1|1
using namespace std;
const int N=3e5+5;
int w,h,n,ans,L,R;
int mx[N*4],tag[N*4];
struct node{int x,y;node(int _x=0,int _y=0):x(_x),y(_y){};}p[N],a[N],b[N];
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*10+c-'0';c=getchar();}
return x*f;
}
void modify(int x,int l,int r,int v)
{
if(L<=l&&r<=R){mx[x]+=v;tag[x]+=v;return;}
int mid=(l+r)>>1;
if(L<=mid)modify(lc(x),l,mid,v);
if(R>mid)modify(rc(x),mid+1,r,v);
mx[x]=max(mx[lc(x)],mx[rc(x)])+tag[x];
}
bool cmp(node a,node b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
void work()
{
memset(mx,0,sizeof(mx));
memset(tag,0,sizeof(tag));
sort(p+1,p+n+1,cmp);
int l=0,r=0;
for(int i=1;i<=n-1;i++)
{
if(p[i].y<=h/2)
{
int nxt=i-1;
while(l&&a[l].y<p[i].y)
{
L=a[l].x;R=nxt;nxt=a[l].x-1;
modify(1,1,n,a[l].y-p[i].y);l--;
}
if(nxt!=i-1)a[++l]=node(nxt+1,p[i].y);
}
else
{
int nxt=i-1;
while(r&&b[r].y>p[i].y)
{
L=b[r].x;R=nxt;nxt=b[r].x-1;
modify(1,1,n,p[i].y-b[r].y);r--;
}
if(nxt!=i-1)b[++r]=node(nxt+1,p[i].y);
}
a[++l]=node(i,0);b[++r]=node(i,h);
L=i;R=i;modify(1,1,n,h-p[i].x);
ans=max(ans,mx[1]+p[i+1].x);
}
}
int main()
{
w=read();h=read();n=read();
for(int i=1;i<=n;i++)p[i].x=read(),p[i].y=read();
p[++n]=node(0,0);p[++n]=node(w,h);work();
for(int i=1;i<=n;i++)swap(p[i].x,p[i].y);
swap(w,h);work();
printf("%d",ans*2);
return 0;
}