Codeforces 651E Table Compression 拓扑序

来源:互联网 发布:电脑压力测试软件 编辑:程序博客网 时间:2024/05/23 15:55
题意:给出n*m矩阵a,要求把矩阵a压缩成矩阵b.b的元素尽量小.并且满足下列条件
若a[i][j]<=a[i][k],则b[i][j]<=b[i][k]
若a[i][j]<=a[p][j] 则b[i][j]<=b[p][j]
 1<=n,m<=1e6 && n*m<=1e6

a[i][j]和其同行同列有着拓扑序(谁比谁小连一条有向边),则从a[i][j]最小的开始填,每次维护行/列的最值即可.

但同行同列中若有相同的? 把这些同行同列相同的数用放到同一个集合,并查集维护要取的值即可.

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=1e6+20;vector< vector<int> >res;struct point{int x,y;point(){}point(int a,int b):x(a),y(b){}bool operator < (const point &t)const{return x==t.x? y<t.y:x<t.x;}};pair<int,point> p[N];int fa[N],mx[N],my[N],mi[N],la[N];void init(int n){for(int i=0;i<n;i++) fa[i]=i;}int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}void Union(int x,int y){int fx=find(x),fy=find(y);fa[fx]=fy;}int main(){int n,m,x;cin>>n>>m;res.resize(n);for(int i=0;i<n;i++)res[i].resize(m);for(int i=0;i<n;i++)for(int j=0;j<m;j++){scanf("%d",&x);p[i*m+j]=make_pair(x,point(i,j));}sort(p,p+n*m);init(n*m);memset(la,-1,sizeof(la));int l=0,r=0;while(l<n*m){while(r<n*m && p[l].first==p[r].first) r++;for(int i=l;i<r;i++){if(i>l && p[i].second.x==p[i-1].second.x)Union(i,i-1);if(~la[p[i].second.y])Union(i,la[p[i].second.y]);la[p[i].second.y]=i;}for(int i=l;i<r;i++){int t=find(i);mi[t]=max(mi[t],mx[p[i].second.x]);mi[t]=max(mi[t],my[p[i].second.y]);}for(int i=l;i<r;i++){int t=find(i);int x=p[i].second.x,y=p[i].second.y;res[x][y]=mi[t]+1;mx[x]=mi[t]+1;my[y]=mi[t]+1;}while(l<r)la[p[l++].second.y]=-1;}for(int i=0;i<n;i++)for(int j=0;j<m;j++)printf("%d%c",res[i][j],j==m-1?'\n':' ');return 0;} 


原创粉丝点击