CF1500C - Matrix Sorting
题目大意
给定矩阵\(A,B\),现在对于\(A\)进行若干次排序操作
每次选择一列,以这一列为关键字对于所有行进行稳定排序
判断是否能够由\(A\)到\(B\)
分析
可以先通过各种暴力方法求得一个 尽量保持相对顺序 的行匹配
然后考虑对于某一列排序造成怎样的贡献
为了得到最终的序列,不妨考虑最终相邻两行之间的关系
然后对于这一列,根据对应的两个数的关系,所有相邻关系在排序之后
1.可能变得符合
2.保持
3.变得不合法
考虑最后一次操作,那么容易发现其必然不包含3类贡献
而且在最后放了一个这个操作之后,可以断定1类位置符合限制
从而将这些位置从限制中删除
由此不断扩展,最后判断极大的扩展是否合法即可
#include<bits/stdc++.h>
using namespace std;
using ull=uint64_t;
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
enum{N=2000,K=2001};
int n,m,A[N][N],B[N][N],I[N],J[N];
ull HA[N],HB[N];
int F[N][N],D[N],del[N],Q[N],L,R;
int main(){
scanf("%d%d",&n,&m);
rep(i,1,n) rep(j,1,m) scanf("%d",A[i]+j),HA[i]=HA[i]*K+A[i][j];
rep(i,1,n) rep(j,1,m) scanf("%d",B[i]+j),HB[i]=HB[i]*K+B[i][j];
rep(i,1,n) rep(j,1,n) if(!J[j] && HB[i]==HA[j]) { I[i]=j,J[j]=i; break; }
rep(i,1,n) if(!I[i]) return puts("-1"),0;
rep(i,1,m) {
rep(j,1,n-1) {
int x=A[I[j]][i],y=A[I[j+1]][i];
F[i][j]=x<y?2:x==y;
if(!F[i][j]) D[i]++;
}
if(!D[i]) Q[++R]=i;
}
while(L<=R) {
int u=Q[L++];
rep(i,1,n-1) if(F[u][i]==2 && !del[i]) {
del[i]=1;
rep(j,1,m) if(!F[j][i] && --D[j]==0) Q[++R]=j;
}
}
rep(i,1,n-1) if(!del[i] && I[i]>I[i+1]) return puts("-1"),0;
printf("%d\n",R);
while(R) printf("%d ",Q[R--]);
}