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("
    ");
        }
    }
  • 相关阅读:
    宋浩《概率论与数理统计》笔记---6.2.1、统计量定义
    宋浩《概率论与数理统计》笔记---6.1、总体与样本
    宋浩《概率论与数理统计》笔记---5.2、中心极限定理
    PHP使用curl替代file_get_contents
    PHP中的ini_set() 函数
    通俗理解中心极限定理
    宋浩《概率论与数理统计》笔记---5.1.2、切比雪夫大数定理
    Options / Lifecycle Hooks
    idea各种图标的含义
    Gradle 基础入门
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5253195.html
Copyright © 2011-2022 走看看