题意:给出n*m矩阵a,要求把矩阵a压缩成矩阵b.b的元素尽量小.并且满足下列条件
若a[i][j]<=a[i][k],则b[i][j]<=b[i][k]
若a[i][j]<=a[p][j] 则b[i][j]<=b[p][j]
1<=n,m<=1e6 && n*m<=1e6
a[i][j]和其同行同列有着拓扑序(谁比谁小连一条有向边),则从a[i][j]最小的开始填,每次维护行/列的最值即可.
若a[i][j]<=a[i][k],则b[i][j]<=b[i][k]
若a[i][j]<=a[p][j] 则b[i][j]<=b[p][j]
1<=n,m<=1e6 && n*m<=1e6
a[i][j]和其同行同列有着拓扑序(谁比谁小连一条有向边),则从a[i][j]最小的开始填,每次维护行/列的最值即可.
但同行同列中若有相同的? 把这些同行同列相同的数用放到同一个集合,并查集维护要取的值即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+20;
vector< vector<int> >res;
struct point{
int x,y;
point(){}
point(int a,int b):x(a),y(b){}
bool operator < (const point &t)const{
return x==t.x? y<t.y:x<t.x;
}
};
pair<int,point> p[N];
int fa[N],mx[N],my[N],mi[N],la[N];
void init(int n){for(int i=0;i<n;i++) fa[i]=i;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void Union(int x,int y)
{
int fx=find(x),fy=find(y);
fa[fx]=fy;
}
int main()
{
int n,m,x;
cin>>n>>m;
res.resize(n);
for(int i=0;i<n;i++)
res[i].resize(m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
scanf("%d",&x);
p[i*m+j]=make_pair(x,point(i,j));
}
sort(p,p+n*m);
init(n*m);
memset(la,-1,sizeof(la));
int l=0,r=0;
while(l<n*m)
{
while(r<n*m && p[l].first==p[r].first) r++;
for(int i=l;i<r;i++)
{
if(i>l && p[i].second.x==p[i-1].second.x)
Union(i,i-1);
if(~la[p[i].second.y])
Union(i,la[p[i].second.y]);
la[p[i].second.y]=i;
}
for(int i=l;i<r;i++)
{
int t=find(i);
mi[t]=max(mi[t],mx[p[i].second.x]);
mi[t]=max(mi[t],my[p[i].second.y]);
}
for(int i=l;i<r;i++)
{
int t=find(i);
int x=p[i].second.x,y=p[i].second.y;
res[x][y]=mi[t]+1;
mx[x]=mi[t]+1;
my[y]=mi[t]+1;
}
while(l<r)
la[p[l++].second.y]=-1;
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
printf("%d%c",res[i][j],j==m-1?'\n':' ');
return 0;
}