Table Compression(思维)
题目链接
题目简述
给定一N*M的表格a,让你对其进行压缩,使得:
- 每一行与每一列相对大小不变,即若\(a_{i,j}>a_{i,k}\),则压缩后的\(a'_{i,j}>a'_{i,k}\),对于小于及等于的情况和同列不同行的情况同理。
- 压缩后表格中的最大值尽量小。
输出压缩后的表格。
数据范围
- \(1<=n,m\)且\(n*m<=1000000\)(即\(1e6\))
- \(a_{i,j}<=1e9\)
解题思路
思维题。首先贪心地把那个在自己所在行所在列最小的元素设为1,然后再去处理比他大1的那些元素。沿着这个思路,我们会发现这整就一个拓扑排序,一个元素可以进入拓扑排序的队列序列,当且仅当所在行所在列比自己小的元素均已经参加了拓扑排序。于是我们的每个元素都建单项边连向同行同列比自己大一点的那个元素,然后跑拓扑就完事了。还有一点是如何处理相等的元素呢?我们进行预处理,用并查集将同行同列相等的元素维护在一起。这些元素在最终的结果中的值一定相等,这是很显然的。
代码实现
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#include <iomanip>
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define ll long long
#define int long long
using namespace std;
typedef __int128 Int;
typedef pair<int,int> pii;
//const int mod=1e9+7;
const int mod=998244353;
void solve(){
int n,m;cin>>n>>m;
vector<vector<int>>a(n+1,vector<int>(m+1));
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>a[i][j];
function<pii(int)>get=[&](int x){
pii temp;temp.fi=(x-1)/m;temp.se=x-temp.fi*m;
return temp;
};
function<int(int,int)>hash=[&](int a,int b){
return (a-1)*m+b;
};
vector<int>p(n*m+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
p[hash(i,j)]=hash(i,j);
function<int(int)>find=[&](int x){
if(p[x]!=x)p[x]=find(p[x]);
return p[x];
};
vector<vector<int>>e(n*m+1);
vector<int>cnt(n*m+1+m);
for(int i=1;i<=n;i++){
vector<pii>temp;
for(int j=1;j<=m;j++){
temp.emplace_back(a[i][j],hash(i,j));
}
sort(temp.begin(),temp.end());
for(int j=1;j<m;j++){
if(temp[j].fi==temp[j-1].fi){
if(find(temp[j].se)!=find(temp[j-1].se))
p[p[temp[j].se]]=p[temp[j-1].se];
}
}
}
for(int i=1;i<=m;i++){
vector<pii>temp;
for(int j=1;j<=n;j++){
temp.emplace_back(a[j][i],hash(j,i));
}
sort(temp.begin(),temp.end());
for(int j=1;j<n;j++){
if(temp[j].fi==temp[j-1].fi){
if(find(temp[j].se)!=find(temp[j-1].se))
p[p[temp[j].se]]=p[temp[j-1].se];
}
}
}
for(int i=1;i<=n;i++){
vector<pii>temp;
for(int j=1;j<=m;j++){
temp.emplace_back(a[i][j],hash(i,j));
}
sort(temp.begin(),temp.end());
e[0].push_back(find(temp[0].se));
cnt[p[temp[0].se]]++;
for(int j=1;j<m;j++){
if(temp[j].fi!=temp[j-1].fi){
e[find(temp[j-1].se)].push_back(find(temp[j].se));
cnt[p[temp[j].se]]++;
}
}
}
for(int i=1;i<=m;i++){
vector<pii>temp;
for(int j=1;j<=n;j++){
temp.emplace_back(a[j][i],hash(j,i));
}
sort(temp.begin(),temp.end());
for(int j=1;j<n;j++){
if(temp[j].fi!=temp[j-1].fi){
e[find(temp[j-1].se)].push_back(find(temp[j].se));
cnt[p[temp[j].se]]++;
}
}
}
vector<int>ans(n*m+1);
stack<int>t;t.push(0);
while(!t.empty()){
int temp=t.top();t.pop();
for(auto i:e[temp]){
ans[i]=max(ans[i],ans[temp]+1);
cnt[i]--;
if(cnt[i]==0){
t.push(i);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout<<ans[find(hash(i,j))]<<" ";
}
cout<<"\n";
}
}
signed main(){
std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
//srand((unsigned)time(NULL));
//int t;std::cin>>t;while(t--)
solve();
}
标签:思维,Compression,temp,int,拓扑,元素,long,Table,define
From: https://www.cnblogs.com/shi5/p/18037604