AT_abc433_e 题解
赛时看错题这一块。以为可以重复。
哇哦,我们发现直接根据
怎么个顺序枚举,从小到大,还是从大到小?明显是从大到小啦,大的数选择余地很少,小的数哪哪都能填啦。
首先你会发现
为之后表述方便,记满足
通过这里我们可以发现一个更加一般化的条件,那就是当存在
这只是一条。我们倒序枚举
有一个很厉害的做法,那就是:如果
处理了满足一个的情况,显然也有一个不满足的情况吧。这个时候我们就得从剩余的格子里找“庇护所”了。所谓“庇护所”的话,就是指某个格子能够填的进去
现在要做的就是维护这些“庇护所”的集合咯,我这边使用了一个 vector 来存储。
这个“庇护所”怎么维护呢?我们发现,当一个
你可能要问了,“庇护”和“庇护所”不都是根据受到“庇护”的那个数的大小而产生的吗,怎么这里只字没提那个数呢?因为你忘了,我们是从大到小枚举
说了这么多废话,还没说到重点上呢。到底如何维护“庇护”的情况以及“庇护所”对应的那个 vector 呢?
考虑再定义两个 vector,分别命名为
接着是维护具体的“庇护所”。依然根据 vector 里了。同理,新列
这些维护的步骤可以考虑写两个函数来处理。
于是这样我们就成功在均摊时间复杂度
最后输出即可。
这就是该题的全部做法咯,不算太难,重点在于“庇护”情况以及“庇护所”的维护。总体时间复杂度是
#include<bits/stdc++.h>
#define LL long long
#define UInt unsigned int
#define ULL unsigned long long
#define LD long double
#define pii pair<int,int>
#define pLL pair<LL,LL>
#define pDD pair<LD,LD>
#define fr first
#define se second
#define pb push_back
#define isr insert
using namespace std;
const int N = 2e5+5;
int T,n,m,a[N],b[N],Nx,Ny;
vector<int> s[N],px,py;
vector<pii> D;bool flag;
int read(){
int su=0,pp=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')pp=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){su=su*10+ch-'0';ch=getchar();}
return su*pp;
}
void InsX(int x){
for(int y:py)
if(!s[x][y])D.pb({x,y});
px.pb(x);return;
}
void InsY(int y){
for(int x:px)
if(!s[x][y])D.pb({x,y});
py.pb(y);return;
}
int main(){
T=read();
while(T--){
n=read(),m=read(),flag=0;
px.clear(),py.clear();
for(int i=1;i<=n;i++)s[i].resize(m+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)s[i][j]=0;
for(int i=1;i<=n*m;i++)a[i]=0,b[i]=0;
for(int i=1;i<=n;i++){int x=read();a[x]=i;}
for(int i=1;i<=m;i++){int x=read();b[x]=i;}
Nx=a[n*m],Ny=b[n*m];
if(!Nx||!Ny){cout<<"No\n";continue;}
px.pb(Nx),py.pb(Ny),s[Nx][Ny]=n*m;
for(int x=n*m-1;x>=1;x--)
if(a[x]&&b[x]){
s[a[x]][b[x]]=x;
InsX(a[x]),InsY(b[x]);
}else if(a[x]||b[x]){
if(a[x])s[a[x]][Ny]=x,InsX(a[x]);
else s[Nx][b[x]]=x,InsY(b[x]);
}else if(D.empty()){flag=1;break;}
else{
auto [i,j]=D.back();
s[i][j]=x;D.pop_back();
}
if(flag){cout<<"No\n";continue;}
cout<<"Yes\n";
for(int i=1;i<=n;cout<<"\n"&&i++)
for(int j=1;j<=m;j++)cout<<s[i][j]<<" ";
}
return 0;
}
如果本篇题解对你有帮助的话,麻烦你点一个小小的赞,真是太感谢啦!