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 ...
随机推荐
- node.js介绍及Win7环境安装测试(转)
官网描述: Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable ...
- Android中使用HttpURLConnection实现GET POST JSON数据与下载图片
Android中使用HttpURLConnection实现GET POST JSON数据与下载图片 Android6.0中把Apache HTTP Client全部的包与类都标记为deprecated ...
- java 内存与内存溢出
学习自:http://www.codeceo.com/article/jvm-memory-overflow.html 讲的很清楚
- cacti 安装和组件添加
安装cacti 步骤 1.准备lamp环境 2.准备所需包:rrdtool(绘图) cacti(安装程序) net-snmpd(数据收集) 3.安装所需库文件 rrdtool所需库文件有: cairo ...
- JavaWeb、J2-SE开发框架——Spring
相关博客: 2.spring官网 1.使用Spring的jdbcTemplate进一步简化JDBC操作
- 做一个合格的程序员之浅析Spring AOP源代码(十八) Spring AOP开发大作战源代码解析
事实上上一篇文章价值非常小,也有反复造轮子的嫌疑,网上AOP的实例非常多,不胜枚举,事实上我要说的并非这个,我想要说的就是上一节中spring的配置文件: 我们这边并没实用到我们上几节分析的哪几个AO ...
- 用户对变量或寄存器进行位操作 、“|=”和“&=~”操作
给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a的bit 3.在以上两个操作中,要保持其他位不变. 答案: ----------------------------------- ...
- python 基础 1.5 数据类型(二)--列表
一.python 数据类型序列---列表 1.列表是可变型的数据类型.列表里边的元素是可变的,可以增加,可以删除. 2.列表(list)是处理一组有序项目的数据结构,即可以在列表中存储一个序列的项 ...
- EasyNVR H5无插件摄像机直播解决方案前端解析之:引用videojs无法自动播放
关于videojs自动播放问题 播放流媒体多使用videojs来进行播放,videojs,本身自带自动播放属性: 通过添加autoplay(),来完成视频播放的自动加载: player = video ...
- [转]C#中的结构体与类的区别
C#中的结构体与类的区别 经常听到有朋友在讨论C#中的结构与类有什么区别.正好这几日闲来无事,自己总结一下,希望大家指点. 1. 首先是语法定义上的区别啦,这个就不用多说了.定义类使用关键字cla ...