Codeforces 650C Table Compression (并查集)

题意:M×N的矩阵 让你保持每行每列的大小对应关系不变,将矩阵重写,重写后的最大值最小。

思路:离散化思想+并查集,详见代码

好题!

 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <cstdlib>
 7 #include <bits/stdc++.h>
 8 using namespace std;
 9 #define clc(a,b) memset(a,b,sizeof(a))
10 const double pi=acos(-1);
11 const int maxn=1000010;
12 int k,n,m,tot,i,j;
13 struct data {
14     int r,c,v,id;
15 } p[maxn];
16 bool cmp(const data &a,const data &b) {
17     return a.v<b.v;
18 }
19 int f[maxn],X[maxn],Y[maxn],x[maxn],y[maxn],ans[maxn],tmp[maxn];
20 
21 int F(int a) {
22     return a==f[a]?f[a]:f[a]=F(f[a]);
23 }
24 
25 int main() {
26     //freopen("in.txt","r",stdin);
27     scanf("%d%d",&n,&m);
28     tot=0;
29     clc(tmp,0);
30     clc(f,-1);
31     for( i=1; i<=n; i++) {
32         for( j=1; j<=m; j++) {
33             scanf("%d",&p[++tot].v);
34             p[tot].r=i,p[tot].c=j;
35             p[tot].id=tot;
36             f[tot]=tot;
37         }
38     }
39     sort(p+1,p+1+tot,cmp);
40     for(i=1; i<=tot; i=j) {
41         for(j=i; p[i].v==p[j].v; j++);//每次只处理相同元素
42         for(k=i; k<j; k++) {//每行每列并查集统计,归并到一个集合
43             int r=p[k].r,c=p[k].c;
44             if(!x[r]) x[r]=k;
45             else
46                 f[F(k)]=F(x[r]);
47             if(!y[c]) y[c]=k;
48             else
49                 f[F(k)]=F(y[c]);
50         }
51         for(k=i; k<j; k++) {//当前值的改变值 应该是该元素所在行或列 前一个填入的值再加一
52             int q=F(k);
53             tmp[q]=max(tmp[q],max(X[p[k].r],Y[p[k].c])+1);
54         }
55         for(k=i; k<j; k++) {//X Y数组维护行和列的最大填入值
56             x[p[k].r]=y[p[k].c]=0;
57             X[p[k].r]=Y[p[k].c]=ans[p[k].id]=tmp[F(k)];
58         }
59     }
60     for(i=1; i<=tot; i++) {
61         if(i%m==1)
62             printf("%d",ans[i]);
63         else
64             printf(" %d",ans[i]);
65         if(i%m==0)
66             printf("\n");
67     }
68     return 0;
69 }
View Code

 

转载于:https://www.cnblogs.com/ITUPC/p/5343472.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值