[CF480E]Parking Lot
Posted StaroForgin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF480E]Parking Lot相关的知识,希望对你有一定的参考价值。
Parking Lot
题解
如果只看求出最大正方形的条件的话是很容易联想到使用笛卡尔树的,然而这道题完全没必要这样写,出题人也想复杂了。
首先看到这种不断让点从能停变成不能停的条件,很容易联想到离线下来反着来,不断让点从不能停变成能停。
我们先对最后的情况求出最大的正方形,很明显,求一次是
O
(
n
m
)
O\\left(nm\\right)
O(nm)的,如果我们不断这样求得话明显是会
T
T
T的。
我们考虑我们更改一个点后会产生怎样的影响。
很明显,如果我们的最大正方形的边长更改了的话,那么改后的正方形一定是包括我们刚刚更改的点的,否则我们的边长不可能变。
我们可以考虑求出包含这个点的最大正方形的边长。
我们可以对于每个点,记录下来它这一行左边第一个已经停车了的点与右边第一个已经停车了的点,分别记作
L
i
,
j
L_{i,j}
Li,j与
R
i
,
j
R_{i,j}
Ri,j。
假设我们的更改的点是
(
x
,
y
)
(x,y)
(x,y),那么我们从第
l
l
l行到第
r
r
r行所能构成的最大正方形的边长应为:
min
(
min
i
=
l
r
R
i
,
y
−
max
i
=
l
r
L
i
,
y
+
1
,
r
−
l
+
1
)
\\min(\\min_{i=l}^{r}R_{i,y}-\\max_{i=l}^{r}L_{i,y}+1,r-l+1)
min(i=lminrRi,y−i=lmaxrLi,y+1,r−l+1)
由于我们的正方形是必然经过点
(
x
,
y
)
(x,y)
(x,y)的,我们可以用一个前缀和的形式记录下区间
(
i
,
x
)
(i,x)
(i,x)中的
min
R
i
,
y
\\min R_{i,y}
minRi,y与
max
L
i
,
y
\\max L_{i,y}
maxLi,y。
我们的左边界,必然是上边界与下边界的
p
r
e
L
preL
preL的最大值,右边界同样是
p
r
e
R
preR
preR的最小值。
它们在中间割出的一段,必然是真空的,可以构成我们的正方形。
我们定义两个边界能匹配,当且仅当中间真空部分能构成一个涵盖上下边界之间所有行的正方形,即该正方形一定能将上下边界都抵满。
当然,我们不能将每个上边界与下边界都匹配,我们只能匹配一部分的。
我们定义
j
<
j
′
⩽
x
j<j'\\leqslant x
j<j′⩽x,其中匹配对象为
k
,
k
′
k,k'
k,k′。
很明显,一定有
k
′
⩾
k
k'\\geqslant k
k′⩾k。
因为当两者都
⩽
x
\\leqslant x
⩽x时,我们的上部分的真空部分的长度一定是在不断扩大的,即
j
′
j'
j′的真空部分一定包含
j
j
j的真空部分,所以
j
′
j'
j′能匹配的一定比
j
j
j能匹配的远。
如果行
i
i
i与
j
j
j能匹配,那么一定可以构造出一个大小为
j
−
i
+
1
j-i+1
j−i+1的正方形。
我们可以用双指针的形式,维护边界间的匹配。
我们只要在每一次变化时,单独为更新一下该列的
L
L
L与
R
R
R,再求一下包含其的最大正方形即可。
时间复杂度
O
(
(
n
+
m
)
k
)
\\mathcal O((n+m)k)
O((n+m)k)
源码
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int mo=1e9+7;
const int inv2=499122177;
const int jzm=2333;
const int lim=1e9;
const int n1=400;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-9;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,m,x,y,len;
double arr[205][205],ans[205],p[205][205][205],answer;
void sakura(){
for(int row=1,col=1;row<len;row++,col++){
int k=row;for(int i=row+1;i<len;i++)if(Fabs(arr[i][col])>Fabs(arr[k][col]))k=i;
if(Fabs(arr[k][col])<eps){row--;continue;}
if(k^row)for(int i=col;i<=len;i++)swap(arr[row][i],arr[k][i]);
for(int i=row+1;i<len;i++){
double tmp=arr[i][col]/arr[row][col];
for(int j=col;j<=len;j++)arr[i][j]-=tmp*arr[row][j];
}
}
for(int i=len-1;i>0;i--){
for(int j=i+1;j<len;j++)arr[i][len]-=arr[i][j]*ans[j];
ans[i]=arr[i][len]/arr[i][i];
}
}
signed main(){
read(n);read(m);read(x);read(y);len=n+m-1;
for(int i=1;i<n;i++)p[i][0][i]=1;
for(int i=1;i<m;i++)p[0][i][i+n-1]=1;
for(int i=1;i<n;i++)
for(int j=1;j<m;j++){
for(int k=1;k<=len;k++)
p[i][j][k]=(p[i-1][j][k]+p[i][j-1][k])/2.0;
p[i][j][len]++;
}
for(int i=1,u=1;i<n;i++,u++){
for(int j=1;j<len;j++)arr[u][j]=0.5*p[i][m-1][j];
arr[u][len]=-1.0-0.5*p[i][m-1][len];
arr[u][u]-=1.0;if(i>1)arr[u][u-1]+=0.5;
}
for(int i=1,u=n;i<m;i++,u++){
for(int j=1;j<len;j++)arr[u][j]=0.5*p[n-1]<以上是关于[CF480E]Parking Lot的主要内容,如果未能解决你的问题,请参考以下文章
CF480E Parking Lot(单调队列+dp然鹅并不是优化)