http://www.codeforces.com/contest/651/problem/E
Little Petya is now fond of data compression algorithms. He has already studied gz, bz, zip algorithms and many others. Inspired by the new knowledge, Petya is now developing the new compression algorithm which he wants to name dis.
Petya decided to compress tables. He is given a table a consisting of n rows and m columns that is filled with positive integers. He wants to build the table a' consisting of positive integers such that the relative order of the elements in each row and each column remains the same. That is, if in some row i of the initial table ai, j < ai, k, then in the resulting table a'i, j < a'i, k, and if ai, j = ai, k then a'i, j = a'i, k. Similarly, if in some column j of the initial table ai, j < ap, j then in compressed table a'i, j < a'p, j and if ai, j = ap, j then a'i, j = a'p, j.
Because large values require more space to store them, the maximum value in a' should be as small as possible.
Petya is good in theory, however, he needs your help to implement the algorithm.
The first line of the input contains two integers n and m (, the number of rows and the number of columns of the table respectively.
Each of the following n rows contain m integers ai, j (1 ≤ ai, j ≤ 109) that are the values in the table.
Output the compressed table in form of n lines each containing m integers.
If there exist several answers such that the maximum number in the compressed table is minimum possible, you are allowed to output any of them.
2 2
1 2
3 4
1 2
2 3
给一个n*m的矩阵,然后让你压缩一下,输出另外一个n*m的矩阵。
这两个矩阵要求在每一行每一列的大小关系保持不变。
比如ai,j<ai,k那么第二个矩阵也得满足这个条件。
从小到大排序,显然最小的数肯定是1,然后第二小的数扔进去,显然就是他所在的行和列已经填过的最大数+1
这很容易想到。
但是相同的数怎么处理?
请用并查集,而不是扫个四五遍。
在同一行同一列的相同元素,就把这两个东西扔进同一个并查集,然后这些元素都是相同的。
那么这些值就等于这一坨所在的行列最大值+1就好了。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
pair<int,pair<int,int> >A[maxn];
map<int,int>X;
map<int,int>Y;
int Hx[maxn],Hy[maxn];
int ans[maxn];
int fa[maxn];
int fi(int u){
return u != fa[u] ? fa[u] = fi( fa[u] ) : u;
}
void uni(int u ,int v){
int p1 = fi( u ) , p2 = fi( v );
if( p1 != p2 ) fa[p1] = p2;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n*m;i++)
{
fa[i]=i;
scanf("%d",&A[i].first);
A[i].second.first=i/m;
A[i].second.second=i%m;
}
int j=-1;
sort(A,A+n*m);
for(int i=0;i<n*m;i++)
{
if(i!=n*m-1&&A[i].first==A[i+1].first)
continue;
for(int k=j+1;k<=i;k++)
{
int p = A[k].second.first*m+A[k].second.second;
int x = A[k].second.first,y=A[k].second.second;
Hx[x]=p;
Hy[y]=p;
}
for(int k=j+1;k<=i;k++)
{
int p = A[k].second.first*m+A[k].second.second;
int x = A[k].second.first,y=A[k].second.second;
uni(Hx[x],p);
uni(Hy[y],p);
}
for(int k=j+1;k<=i;k++)
{
int p = A[k].second.first*m+A[k].second.second;
int x = A[k].second.first,y=A[k].second.second;
int pa = fi(p);
ans[pa]=max(ans[pa],max(X[x],Y[y])+1);
}
for(int k=j+1;k<=i;k++)
{
int p = A[k].second.first*m+A[k].second.second;
int x = A[k].second.first,y=A[k].second.second;
X[x]=max(X[x],ans[fi(p)]);
Y[y]=max(Y[y],ans[fi(p)]);
}
j=i;
}
for(int i=0;i<n*m;i++)
{
printf("%d ",ans[fi(i)]);
if(i%m==m-1)printf("\n");
}
}