题目大意:
给你一个矩阵,然后修改矩阵,让所有的列和行的大小关系保持不变
思路:
感觉这道题犯2了好久,看别人的思路半天都不知道该怎么做,然后试着敲了一下,结果原因是因为operate这里错了,然后果断直接改成了cmp,还是简单粗暴一点的比较好。
首先因为范围很大,刚开始我想的是排序以后离散化,但是离散化以后就不会做了。。。
然后看了一下题解以后发现,通过并查集来维护关系。
首先我们从大到小排序以后,然后从第一个开始枚举所有的数字,然后遇到相同的数字就continue,并用lb来维护左端的值。接着,我们将所有值相同的,同一行同一列的都保存为一个点(利用并查集的路径压缩),并且在这个时候要记得将cnt的值不断更新。
然后跳出当前循环以后,我们要重新枚举当前的ans值,然后再这个之中我们也要记得维护maxx和maxy(当前行列的最大值)的值,就可以了。
#include
using namespace std;
const int maxn = 1000000 + 5;
int n, m;
struct point{
int x, y;
int val;
};
point my[maxn], mx[maxn];
point now[maxn];
int ans[maxn], cnt[maxn], par[maxn];
int maxx[maxn], maxy[maxn];
int cal(int x, int y){
return x * m + y;
}
void init(){
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
int tmp;
scanf("%d", &tmp);
int p = cal(i, j);
now[p].x = i;
now[p].y = j;
now[p].val = tmp;
par[p] = p;
}
}
}
int pfind(int x){
if (par[x] == x) return x;
return par[x] = pfind(par[x]);
}
xcheck(int x, int y, int val, int r){
if (mx[x].val < val){
mx[x].val = val;
mx[x].x = x;
mx[x].y = y;
}
else {
int px = cal(mx[x].x, mx[x].y);
px = pfind(px);
if (r != px){
cnt[r] = max(cnt[r], cnt[px]);
par[px] = r;
}
}
}
void ycheck(int x, int y, int val, int r){
if (my[y].val < val){
my[y].val = val;
my[y].x = x;
my[y].y = y;
}
else {
int py = cal(my[y].x, my[y].y);
py = pfind(py);
if (py != r){
cnt[r] = max(cnt[r], cnt[py]);
par[py] = r;
}
}
}
bool cmp (const point &a, const point &b){
return a.val < b.val;
}
void solve(){
sort(now, now + n * m, cmp);
//printf("%d %d %d\n", now[1].x, now[1].y, now[1].val);
int lb = 0;
for (int i = 1; i <= n*m; i++){
if (now[i].val == now[i - 1].val) continue;
int g = i - 1;
for (int j = lb; j <= g; j++){
int x = now[j].x;
int y = now[j].y;
int val = now[j].val;
int r = cal(x, y);
r = pfind(r);
xcheck(x, y, val, r);
ycheck(x, y, val, r);
cnt[r] = max(cnt[r], max(maxx[x], maxy[y]));
}
for (int j = lb; j <= g; j++){
int pla = cal(now[j].x, now[j].y);
//printf("pla = %d\n", pla);
int ro = pfind(pla);
//if (j == 3) printf("cnt[3] = %d r = %d pla = %d\n", cnt[pfind(j)], pfind(j), pla);
ans[pla] = cnt[ro] + 1;
maxx[now[j].x] = max(maxx[now[j].x], ans[pla]);
maxy[now[j].y] = max(maxy[now[j].y], ans[pla]);
}
//printf("%d\n", lb);
lb = i;
}
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
printf("%d%c", ans[cal(i, j)], j == m-1 ? '\n' : ' ');
}
}
}
int main(){
init();
solve();
return 0;
}