codeforces 651E E. Table Compression(贪心+并查集)
题目链接:
4 seconds
256 megabytes
standard input
standard output
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
4 3
20 10 30
50 40 30
50 60 70
90 80 70
2 1 3
5 4 3
5 6 7
9 8 7 题意: 给一个n*m的矩阵,要你在不该变任意一行或一列中两个数的大小关系使得这个矩阵的最大值最小; 思路: 假设这些数全部都不相等,那么我们可以排序后再按从小到大的顺序插入到原来的位置上,插入的是这个位置所在行和列的最大数+1,而现在其中有些数相同,
思考后可知,相等的数不在同行或同列时互相没有影响,跟上述插入方式一样,但是如果在同行或者同列,那么位置插入的数的大小应该相同,且是这些位置的所在行和列的最大值+1;
所以我们把在同行或者同列的相同的数放在一个集合里面,改变一个的时候全部改变,这就可以用并查集了;
具体的实现看代码; AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bits/stdc++.h>
#include <stack>
#include <map> using namespace std; #define For(i,j,n) for(int i=j;i<=n;i++)
#define mst(ss,b) memset(ss,b,sizeof(ss)); typedef long long LL; template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
if(!p) { puts("0"); return; }
while(p) stk[++ tp] = p%10, p/=10;
while(tp) putchar(stk[tp--] + '0');
putchar('\n');
} const LL mod=1e9+7;
const double PI=acos(-1.0);
const int inf=1e9;
const int N=1e6+120;
const int maxn=210;
const double eps=1e-12; int n,m,a[N],p[N],l[N],r[N],vis[N],ans[N];
vector<int>ve[N];
struct node
{
int a,id,i,j;
}po[N];
int cmp1(node x,node y)
{
if(x.a==y.a)return x.i<y.i;
return x.a<y.a;
}
int cmp2(node x,node y)
{
if(x.a==y.a)return x.j<y.j;
return x.a<y.a;
}
int findset(int x)
{
if(p[x]==x)return x;
return p[x]=findset(p[x]);
}
int same(int x,int y)
{
int fx=findset(x),fy=findset(y);
if(fx<fy)p[fy]=fx;
else if(fx>fy)p[fx]=fy;
} int main()
{
int cnt=0;
read(n);read(m);
For(i,0,n*m)p[i]=i;
For(i,1,n)
{
For(j,1,m)
{
cnt++;
po[cnt].id=cnt;
po[cnt].i=i;po[cnt].j=j;
read(po[cnt].a);
}
}
sort(po+1,po+cnt+1,cmp2);//两次排序把在同行和同列的相同的数合并
For(i,2,cnt)
{
if(po[i].a==po[i-1].a&&po[i].j==po[i-1].j)same(po[i].id,po[i-1].id);
}
sort(po+1,po+cnt+1,cmp1);
For(i,2,cnt)
{
if(po[i].a==po[i-1].a&&po[i].i==po[i-1].i)same(po[i].id,po[i-1].id);
}
For(i,1,cnt)//可以由root找到这个集合所有数所在的位置;
{
int root=findset(po[i].id);
ve[root].push_back(i);
}
For(i,1,cnt)
{
int root=findset(po[i].id);
if(!vis[root])
{
int temp=0,len=ve[root].size();//对root一次操作改变这个集合里面所有元素的答案;
for(int j=0;j<len;j++)
{
int x=ve[root][j];
temp=max(temp,r[po[x].i]);
temp=max(temp,l[po[x].j]);
}
temp++;ans[root]=temp;
for(int j=0;j<len;j++)
{
int x=ve[root][j];
l[po[x].j]=r[po[x].i]=temp;
}
vis[root]=1;
}
ans[po[i].id]=ans[root];
}
For(i,1,n)
{
For(j,1,m-1)printf("%d ",ans[(i-1)*m+j]);
printf("%d\n",ans[i*m]);
}
return 0;
}
codeforces 651E E. Table Compression(贪心+并查集)的更多相关文章
- Codeforces #345div1 C Table Compression (650C) 并查集
题意:给你一个n*m的矩阵,需要在不改变每一行和每一列的大小关系的情况下压缩一个矩阵,压缩后的矩阵所有数的总和尽量的小. 思路:我们有这样的初步设想:对于在一行或一列的数x,y,若x<y,则建立 ...
- Codeforces 651E Table Compression【并查集】
题目链接: http://codeforces.com/problemset/problem/650/C 题意: 给定n*m的矩阵,要求用最小的数表示每个元素,其中各行各列的大小关系保持不变. 分析: ...
- Codeforces Round #345 (Div. 1) C. Table Compression dp+并查集
题目链接: http://codeforces.com/problemset/problem/650/C C. Table Compression time limit per test4 secon ...
- codeforces Codeforces Round #345 (Div. 1) C. Table Compression 排序+并查集
C. Table Compression Little Petya is now fond of data compression algorithms. He has already studied ...
- Codeforces Round #345 (Div. 2) E. Table Compression(并查集)
传送门 首先先从小到大排序,如果没有重复的元素,直接一个一个往上填即可,每一个数就等于当前行和列的最大值 + 1 如果某一行或列上有重复的元素,就用并查集把他们连起来,很(不)显然,处于同一行或列的相 ...
- POJ 1456 Supermarket(贪心+并查集)
题目链接:http://poj.org/problem?id=1456 题目大意:有n件商品,每件商品都有它的价值和截止售卖日期(超过这个日期就不能再卖了).卖一件商品消耗一个单位时间,售卖顺序是可以 ...
- Codeforces 437D The Child and Zoo(贪心+并查集)
题目链接:Codeforces 437D The Child and Zoo 题目大意:小孩子去參观动物园,动物园分非常多个区,每一个区有若干种动物,拥有的动物种数作为该区的权值.然后有m条路,每条路 ...
- Codeforces Round #376 (Div. 2) C. Socks---并查集+贪心
题目链接:http://codeforces.com/problemset/problem/731/C 题意:有n只袜子,每只都有一个颜色,现在他的妈妈要去出差m天,然后让他每天穿第 L 和第 R 只 ...
- Codeforces 437D 贪心+并查集
这个题目让我想起了上次在湘潭赛的那道跪死了的题.也是最值问题,这个也是,有n个动物园 每个都有权值 然后被m条路径相连接,保证图是连通的,然后求所有的p[i][j]之和.i,j为任意两个zoo,pij ...
随机推荐
- hdu2141Can you find it?
给你四个集合.要你从这四个集合中 各取出一个数出来,推断,取出的前三个数的和 是否等于第四个数. 数据比較大.我的做法是将 前两个集合全部数全部和的情况取出来, 然后二分查找第四个集合和第三集合 ...
- ARM和STM32的区别及ARM公司架构的发展
ARM和STM32的区别及ARM公司架构的发展 转:https://www.cnblogs.com/kwdeblog/p/5260348.html ARM是英国的芯片设计公司,其最成功的莫过于32位嵌 ...
- 使用构建工具gradle打包时,遇到的中文问题和解决方式
1.使用gradle clean war 命令将项目打成war包.这一过程gradle没有提示报错. 2.将得到的myapp.war复制到tomcat下webapps(部署war包) 3.启动to ...
- Android Handler 异步消息处理机制的妙用 创建强大的图片载入类
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38476887 ,本文出自[张鸿洋的博客] 近期创建了一个群.方便大家交流,群号: ...
- 树莓派 CPU & 主板 温度
CPU cat /sys/class/thermal/thermal_zone0/temp | awk '{print $1/1000}' 主板 /opt/vc/bin/vcgencmd measur ...
- 一张图帮你看懂 iPhone 6 Plus 的屏幕分辨率
一张图帮你看懂 iPhone 6 Plus 的屏幕分辨率 几天前公布的 iPhone 6 Plus 官方标称屏幕是 1920 x 1080 的,可是在 Xcode 中我们发现模拟器的屏幕事实上是看似奇 ...
- windows下如何快速优雅的使用python的科学计算库?
Python是一种强大的编程语言,其提供了很多用于科学计算的模块,常见的包括numpy.scipy.pandas和matplotlib.要利用Python进行科学计算,就需要一一安装所需的模块,而这些 ...
- 常用string函数分析
string函数分析string函数包含在string.c文件中,经常被C文件使用.1. strcpy函数原型: char* strcpy(char* str1,char* str2);函数功能: 把 ...
- 在linux系统中I/O 调度的选择 (转)
I/O 调度算法再各个进程竞争磁盘I/O的时候担当了裁判的角色.他要求请求的次序和时机做最优化的处理,以求得尽可能最好的整体I/O性能. 在linux下面列出4种调度算法 CFQ (Completel ...
- Linux 开启端口,操作防火墙
命令行方式: 添加10002端口方法 1.vi etc/sysconfig/iptables 2. 开放端口命令:-A INPUT -p tcp -m state --state NEW -m ...