Codeforces 650 C. Table Compression

Solution

最坑不过读错题

一开始读错题了…看成相邻格子比大小了- –

我们可以先用并查集合并相同数字的格子。

然后根据数字在行/列中的大小建立一个拓扑图,由小格子->大格子建边,求一下这个东东的拓扑序就好了,答案就是拓扑序的深度。

由于数据比较大,我们可以用优先队列优化求每行每列最大值的操作,复杂度比较低一些。

但是偶写的太丑啦…速度慢慢的VerySlow…

\[O(N*\log(N*M)+M*\log(N*M))\]
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int INF = 1<<30;
typedef long long LL;
int getint() {
	int r = 0, k = 1; char c = getchar();
	for (; '0' > c || c > '9'; c = getchar()) if (c == '-') k = -1;
	for (; '0' <= c && c <= '9'; c = getchar()) r = r * 10 - '0' + c;
	return r * k;
}
const int maxnm = 1000005;
int n, m;
struct datatype {
	int a[maxnm];
	int b[maxnm];
	int get(int h, int l) { return a[(h-1)*m+l]; }
	int getb(int h, int l) { return b[(h-1)*m+l]; }
	int id(int h, int l) { return (h-1)*m+l; }
} A;
int tot = 0;
int f[maxnm];
int q[maxnm];
int col[maxnm], coll[maxnm], rd[maxnm], h[maxnm];
struct edge_type {
	int to, next;
} edge[maxnm * 5];
int cnte = 1;
void ins(int u, int v) {
	edge[++cnte].to = v;
	edge[cnte].next = h[u];
	h[u] = cnte;
	++rd[v];
}
void tppx() {
	int head = 0, tail = 0;
	for (int i = 1; i <= tot; ++i) if (rd[i] == 0) q[tail++] = i, col[i] = 1;
	int now;
	while (head < tail) {
		now = q[head++];
		for (int i = h[now]; i; i = edge[i].next) {
			rd[edge[i].to] --;
			if (rd[edge[i].to] == 0) { q[tail++] = edge[i].to; col[edge[i].to] = col[now] + 1; }
		}
	}
}
int find(int x) { return f[x] == x ? x : find(f[x]); }
struct my_type {
    int val, id;
    my_type () { val = 0; id = 0; }
    my_type (int v, int d) { val = v; id = d; }
};
bool operator < (my_type a, my_type b) { return a.val < b.val; }
priority_queue<my_type> pq;
bool allsame = true;
int main() {
	n = getint(); m = getint();
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j) {
			A.a[++tot] = getint();
			f[tot] = tot;
		}
	my_type tmp, lst;
	for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) pq.push(my_type(A.get(i, j), find(A.id(i, j))));
		tmp = pq.top();
		pq.pop();
		while (!pq.empty()) {
			lst = tmp;
			tmp = pq.top(); pq.pop();
			if (tmp.val == lst.val) f[find(tmp.id)] = find(lst.id);
		}
	}
	for (int j = 1; j <= m; ++j) {
        for (int i = 1; i <= n; ++i) pq.push(my_type(A.get(i, j), find(A.id(i, j))));
		tmp = pq.top();
		pq.pop();
		while (!pq.empty()) {
			lst = tmp;
			tmp = pq.top(); pq.pop();
			if (tmp.val == lst.val) f[find(tmp.id)] = find(lst.id);
		}
	}
	for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) pq.push(my_type(A.get(i, j), find(A.id(i, j))));
		tmp = pq.top();
		pq.pop();
		while (!pq.empty()) {
			lst = tmp;
			tmp = pq.top(); pq.pop();
			if (lst.val == tmp.val) continue;
			ins(find(tmp.id), find(lst.id));
		}
	}
	for (int j = 1; j <= m; ++j) {
        for (int i = 1; i <= n; ++i) pq.push(my_type(A.get(i, j), find(A.id(i, j))));
		tmp = pq.top();
		pq.pop();
		while (!pq.empty()) {
			lst = tmp;
			tmp = pq.top(); pq.pop();
			if (lst.val == tmp.val) continue;
			ins(find(tmp.id), find(lst.id));
		}
	}
	tppx();
	for (int i = 1; i <= tot; ++i) A.b[i] = col[find(i)];
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j)
			printf("%d ", A.getb(i, j));
		printf("\n");
	}
}