题解:P9514 [JOI Open 2023] 花园 / Garden
Meta_Morph · · 题解
[JOI Open 2023] 花园 / Garden 题解
博客园链接:[JOI Open 2023] 花园 / Garden 题解 - Add_Catalyst - 博客园 (cnblogs.com)。
知识点
单调队列。
分析
首先可以看出所有的坐标范围都只需要在
这类求矩形面积相关的题目有一个套路:枚举左下角,那么它的两维范围是
A 类比较简单,它的存在只是让我们固定了最小范围,比如一个
-
- $x\le P$,$x'\ge P$。 - $x > P$,$x'\ge P+D$。 -
- $y\le Q$,$y'\ge Q$。 - $y > Q$,$y'\ge Q+D$。
所以 A 类可以开两个
B 类其实也一样,对于一个
-
- $x\le R$,$x'\ge R$。 - $x > R$,$x'\ge R+D$。 -
- $y\le S$,$y'\ge S$。 - $y > S$,$y'\ge S+D$。
现在枚举左下角
考虑单调队列做法,枚举每个
那么我们得到了一个
发现每次
然后单调队列中的值只需要在
注意有一些边界条件要特殊处理。
总复杂度
代码
constexpr int N(5e5+10),_D(5e3+10);
int n,m,D,ans;
int AX[_D],AY[_D],BX[_D<<1];
vector<int> vec[_D];
int cal(int xa,int xb,int ya,int yb) { return (xb-xa+1)*(yb-ya+1); }
signed main() {
#ifdef plus_cat
freopen(plus_cat ".in","r",stdin),freopen(plus_cat ".out","w",stdout);
#endif // plus_cat
/*DE("Input");*/
scanf("%d%d%d",&n,&m,&D),ans=D*D;
/*DE("Solve A class");*/
FOR(i,1,n) {
int x,y;
scanf("%d%d",&x,&y);
tomax(AX[0],x),tomax(AX[x+1],x+D);
tomax(AY[0],y),tomax(AY[y+1],y+D);
}
FOR(i,1,D)tomax(AX[i],i,AX[i-1]),tomax(AY[i],i,AY[i-1]);
/*DE("Record B class");*/
FOR(y,0,2*D-1)BX[y]=0;
FOR(i,1,m) {
int x,y;
scanf("%d%d",&x,&y);
if(y>0)tomax(BX[y-1],x);
tomax(BX[y+D-1],x),vec[x+1].push_back(y);
}
/*DE("Solve");*/
FOR(x,0,D-1) {
tomin(ans,cal(x,AX[x],0,D-1));
for(int y:vec[x]) {
if(y>0)tomax(BX[y-1],x+D-1);
tomax(BX[y+D-1],x+D-1);
}
int it(0),h(1),t(0);
static int q[_D<<1];
auto update=[&](int i,int y) {
if(y<0)return;
int _y(max(q[i-1]+1,AY[y]));
tomin(ans,cal(x,max(AX[x],BX[q[i]]),y,_y));
};
FOR(y,0,D-1) {
while(it<y+D-1) {
while(h<=t&&BX[it]>BX[q[t]])update(t--,y-1);
q[++t]=it++;
}
while(h<=t&&q[h]<AY[y])update(h++,y-1);
}
while(h<=t)update(h++,D-1);
}
/*DE("Output");*/
printf("%d\n",ans);
return 0;
}