zoukankan      html  css  js  c++  java
  • Codeforces Round #345 (Div. 2) E. Table Compression 并查集

    E. Table Compression

    题目连接:

    http://www.codeforces.com/contest/651/problem/E

    Description

    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.

    Input

    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

    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.

    Sample Input

    2 2
    1 2
    3 4

    Sample Output

    1 2
    2 3

    Hint

    题意

    给一个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("
    ");
        }
    }
  • 相关阅读:
    分页存储过程
    C#,单元测试
    telerik reporting报表
    在Linq to sql 和 Entity framework 中使用lambda表达式实现left join
    .NET提供了三种后台输出js的方式:
    转换人民币大小金额
    ASP.Net Post方式获取数据流的一种简单写法
    js数组中两个有相同删除一个
    我的个人博客
    It is the courage
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5253195.html
Copyright © 2011-2022 走看看