CF650C Table Compression

给一个 \(n\times m\) 的非负整数矩阵 \(a\),让你求一个 \(n\times m\) 的非负整数矩阵 \(b\),满足以下条件

  1. 若 \(a_{i,j}<a_{i,k}\),则 \(b_{i,j}<b_{i,k}\)
  2. 若 \(a_{i,j}=a_{i,k}\),则 \(b_{i,j}=b_{i,k}\)
  3. 若 \(a_{i,j}<a_{k,j}\),则 \(b_{i,j}<b_{k,j}\)
  4. 若 \(a_{i,j}=a_{k,j}\),则 \(b_{i,j}=b_{k,j}\)
  5. \(b\) 中的最大值最小

\(n\times m\leq 10^6\)

建图+并查集


先考虑 \(a\) 中没有重复元素的情况

发现,我们只需要对于每行每列,按值域从小到大,相邻两位置连边,然后 \(b\) 每个位置的权值即为到最小数的距离,在 DAG 上遍历一遍即可

但是若 \(a\) 中有重复元素,直接建图就没有正确性了

\(trick\) :对于同一行同一列的重复元素,建立并查集,进行操作时只用对根节点进行操作

时间复杂度 \(O(nm\log nm)\)

代码

#include <bits/stdc++.h>
using namespace std; #define get(x, y) ((x - 1) * m + y)
typedef pair <int, int> pii;
const int maxn = 1e6 + 10;
int n, m, tot, a[maxn], f[maxn], par[maxn];
struct node {
int x, y;
bool operator < (const node& o) const {
return a[get(x, y)] < a[get(o.x, o.y)];
}
} dat[maxn];
vector <int> g[maxn]; int find(int x) {
return par[x] == x ? x : par[x] = find(par[x]);
} void unite(int x, int y) {
par[find(x)] = find(y);
} int dfs(int u) {
if (~f[u]) return f[u]; f[u] = 0;
for (int v : g[u]) f[u] = max(f[u], dfs(v));
return ++f[u];
} int main() {
scanf("%d %d", &n, &m), tot = n * m;
for (int i = 1; i <= tot; i++) {
scanf("%d", a + i), par[i] = i;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
dat[j] = node{i, j};
}
sort(dat + 1, dat + m + 1);
for (int j = 1; j < m; j++) {
int u = get(dat[j].x, dat[j].y);
int v = get(dat[j + 1].x, dat[j + 1].y);
if (a[u] == a[v]) unite(u, v);
}
}
for (int j = 1; j <= m; j++) {
for (int i = 1; i <= n; i++) {
dat[i] = node{i, j};
}
sort(dat + 1, dat + n + 1);
for (int i = 1; i < n; i++) {
int u = get(dat[i].x, dat[i].y);
int v = get(dat[i + 1].x, dat[i + 1].y);
if (a[u] == a[v]) unite(u, v);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
dat[j] = node{i, j};
}
sort(dat + 1, dat + m + 1);
for (int j = 1; j < m; j++) {
int u = get(dat[j].x, dat[j].y);
int v = get(dat[j + 1].x, dat[j + 1].y);
if ((u = find(u)) != (v = find(v))) g[v].push_back(u);
}
}
for (int j = 1; j <= m; j++) {
for (int i = 1; i <= n; i++) {
dat[i] = node{i, j};
}
sort(dat + 1, dat + n + 1);
for (int i = 1; i < n; i++) {
int u = get(dat[i].x, dat[i].y);
int v = get(dat[i + 1].x, dat[i + 1].y);
if ((u = find(u)) != (v = find(v))) g[v].push_back(u);
}
}
memset(f, -1, sizeof f);
for (int i = 1; i <= tot; i++) {
if (find(i) == i) dfs(i);
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
printf("%d ", f[find(get(i, j))]);
}
putchar(10);
}
return 0;
}

一种 \(shortest\) 的做法

对于每个元素,按值域从小到大考虑,通过已访问到的行列最大值更新答案

时间复杂度 \(O(nm\log nm)\)

代码

#include <bits/stdc++.h>
using namespace std; #define get(x, y) ((x - 1) * m + y)
const int maxn = 1e6 + 10;
int n, m, tot, a[maxn], ans[maxn], par[maxn], val[2][maxn];
struct node {
int x, y;
bool operator < (const node& o) const {
return a[get(x, y)] < a[get(o.x, o.y)];
}
} dat[maxn]; int find(int x) {
return par[x] == x ? x : par[x] = find(par[x]);
} int main() {
scanf("%d %d", &n, &m), tot = n * m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
int pos = get(i, j);
scanf("%d", a + pos), dat[pos] = node{i, j}, par[pos] = pos;
}
}
sort(dat + 1, dat + tot + 1);
for (int i = 1; i <= tot; i++) {
int tx = dat[i].x, ty = dat[i].y, pos = get(tx, ty);
int px = find(val[0][tx]), py = find(val[1][ty]), p = find(pos);
ans[p] = max(ans[px] + (a[p] > a[px]), ans[py] + (a[p] > a[py]));
if (a[p] == a[px]) par[px] = p;
if (a[p] == a[py]) par[py] = p;
val[0][tx] = val[1][ty] = p;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
printf("%d ", ans[find(get(i, j))]);
}
putchar(10);
}
return 0;
}

CF650C Table Compression的更多相关文章

  1. 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 ...

  2. Codeforces Round #345 (Div. 1) C. Table Compression dp+并查集

    题目链接: http://codeforces.com/problemset/problem/650/C C. Table Compression time limit per test4 secon ...

  3. Code Forces 650 C Table Compression(并查集)

    C. Table Compression time limit per test4 seconds memory limit per test256 megabytes inputstandard i ...

  4. Codeforces Round #345 (Div. 2) E. Table Compression 并查集

    E. Table Compression 题目连接: http://www.codeforces.com/contest/651/problem/E Description Little Petya ...

  5. Oracle Schema Objects——Tables——Table Compression

    Oracle Schema Objects Table Compression 表压缩 The database can use table compression to reduce the amo ...

  6. codeforces 651E E. Table Compression(贪心+并查集)

    题目链接: E. Table Compression time limit per test 4 seconds memory limit per test 256 megabytes input s ...

  7. MySQL 5.6 Reference Manual-14.7 InnoDB Table Compression

    14.7 InnoDB Table Compression 14.7.1 Overview of Table Compression 14.7.2 Enabling Compression for a ...

  8. Codeforces Round #345 (Div. 2) E. Table Compression 并查集+智商题

    E. Table Compression time limit per test 4 seconds memory limit per test 256 megabytes input standar ...

  9. Codeforces 650C Table Compression

    传送门 time limit per test 4 seconds memory limit per test 256 megabytes input standard input output st ...

随机推荐

  1. 浅谈pc和移动端的响应式

    身为一个前端攻城狮,是不是经常遇到各种各样的响应式问题?下面我们来说一下: 1.响应式跟自适应有什么区别? 有些人可能还不知道响应式跟自适应的区别,甚至认为他们是同一个东西,其实不是的. 自适应是最早 ...

  2. Wyn BI的机会在哪里:越靠近消费者的行业,比如零售、文娱和金融,信息化投入越大 ZT

    近日,全球知名信息技术咨询公司IDC在网易云创大会上发布了<2018中国企业数字化发展报告>(下称报告).报告显示,近几年我国数字经济占GDP比重逐年增加,至2017年已经达到32.9%, ...

  3. Java:注解Annotation(元数据)

    本文内容: 注解Annotation的介绍 基本注解的用法 自定义注解 首发日期:2018-07-28 注解Annotation的介绍 Annotation是代码中的特殊标记,能够在编译.类加载.运行 ...

  4. Essential pro angular and asp.net core 笔记

    1. dotnet ef相关命令 删除数据库(适合只有一个数据库的情形) dotnet ef database drop --force 更新数据库(适合只有一个数据库的情形) dotnet ef d ...

  5. sql server 分组,取每组的前几行数据

    sql中group by后,获取每组中的前N行数据,目前我知道的有2种方法 比如有个成绩表: 里面有字段学生ID,科目,成绩.我现在想取每个科目的头三名. 1.   子查询 select * from ...

  6. 解决Protege打开owl文件时程序卡死问题

    Protege在打开本地owl文件时,程序卡死,而且在终端或是命令行中也没有报错.这是因为存放该本体的文件夹下面有很多其他的文件,只需要创建一个新的文件夹并把owl文件放入其中就可以解决该问题.

  7. C# DBHelper类 参考

    using System;using System.Collections.Generic;using System.Text;using System.Configuration;using Sys ...

  8. centOS7docker安装oracle

    1.拉取oracle 11g 的镜像: 用root登陆服务器,输入下面的命令,拉取oracle 11g的镜像,有点大,6.8G多: docker pull registry.cn-hangzhou.a ...

  9. 排序算法之直接插入排序的思想以及Java实现

    1,基本思想 假设待排序的数据是数组A[1-.n].初始时,A[1]自成1个有序区,无序区为A[2-.n].在排序的过程中,依次将A[i] (i=2,3,-.,n)从后往前插入到前面已排好序的子数组A ...

  10. C# -- 随机数产生的字母金字塔

    C# -- 随机数产生的字母金字塔 1. 代码实现: static void Main(string[] args) { showNpoint(); Console.ReadKey(); } priv ...