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. 基于timestamp和nonce的防重放攻击

    以前总是通过timestamp来防止重放攻击,但是这样并不能保证每次请求都是一次性的.今天看到了一篇文章介绍的通过nonce(Number used once)来保证一次有效,感觉两者结合一下,就能达 ...

  2. 基于Aspectj 注解实现 spring AOP

    AOP 面向切面编程,是 OOP (面向对象编程)的补充 术语 横切关注点:方法中非主要业务逻辑部分 比如运算的模块:有验证参数.执行方法前的操作.执行方法.执行方法后的操作,验证参数.执行方法前后的 ...

  3. Android样式主题及自定义属性

    一.Selector——图形.颜色选择器 语法 <selector>   <item android:drawable=“drawableResA” android:state_xx ...

  4. 直接通过Binder的onTransact完成跨进程通信

    1.具体代码: 服务端实现: public class IPCService extends Service { private static final String DESCRIPTOR = &q ...

  5. Flutter 布局(二)- Padding、Align、Center详解

    本文主要介绍Flutter布局中的Padding.Align以及Center控件,详细介绍了其布局行为以及使用场景,并对源码进行了分析. 1. Padding A widget that insets ...

  6. 用户不在 sudoers 文件中,此事将被报告

    在使用Linux系统过程中,通常情况下,我们都会使用普通用户进行日常操作,而root用户只有在权限分配及系统设置时才会使用,而root用户的密码也不可能公开.普通用户执行到系统程序时,需要临时提升权限 ...

  7. A problem has been detected and windows has been shut down to prevent damage to your computer.他么啥意思?看这里!【蓝屏】

    A problem has been detected and windows has been shut down to prevent damage to your computer.  检测到问 ...

  8. Linux下2号进程的kthreadd--Linux进程的管理与调度(七)

    2号进程 内核初始化rest_init函数中,由进程 0 (swapper 进程)创建了两个process init 进程 (pid = 1, ppid = 0) kthreadd (pid = 2, ...

  9. Android Studio教程03-Activtiy生命周期的理解

    目录 1. Activity 1.1. 安卓中的Activity定义和特性: 1.2. 注册Activity 1. Intent filters:设置默认开启的activity 1.3. Activi ...

  10. nginx 拦截 swagger 登录

    随着微服务的也来越多,每个服务都有单独的文档,那么问题来了,怎么把所有文档整合在一起呢 本方法采用服务器拦截的方式进行处理 首先需要在opt 的主目录中 /opt/ 创建一个新文件 htpasswd此 ...