题目链接
题目大意
给你一个\(n \times m(n\times m\leq 250000)\)的矩阵
你要构造一个长度为\(m(1\leq a[i] \leq 1e9)\)的数组,使得矩阵每一行的元素最多2个和他不同
题目思路
其实看到这个很容易想到枚举,因为只有至多两个元素不同
但是如何枚举却是一个问题
1:其他行的元素与第一行的元素不同的值最多为2那么显然可以直接输出第一行元素
2:其他行的元素与第一行的元素不同的值最多大于4那么显然直接输出No
3: 关键是如果最大值是3/4该怎么办,显然假设现在答案为第一行元素,那么答案必定要改变一个值为另一个序列的值,还有可能还要改变一个值,但是暂时不知道要改什么,先设为-1。用新序列去与所有序列比较,当不同数大于3的时候,那就不合理。当不同数为3的时候,如果这个时候存在-1,那么将-1改成和当前序列这个位置相同的数,否则就不合理。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5e4+5;
vector<int> vec[maxn];
int n,m;
int cal(vector<int> a,vector<int> b){ //计算机两个数组的不同值
int cnt=0;
for(int i=1;i<=m;i++){
cnt+=(a[i]!=b[i]);
}
return cnt;
}
void pr(vector<int> a){
for(int i=1;i<=m;i++){
if(a[i]==-1) a[i]=1;
printf("%d%c",a[i],i==m?'\n':' ');
}
}
void check(vector<int> temp){
for(int i=1;i<=n;i++){
if(cal(temp,vec[i])>3){
return ;
}else if(cal(temp,vec[i])==3){
for(int j=1;j<=m;j++){
if(temp[j]==-1){
temp[j]=vec[i][j];
break;
}
if(j==m){
return ;
}
}
}
}
printf("Yes\n");
pr(temp);
exit(0);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
vec[i].push_back(-1);
for(int j=1,x;j<=m;j++){
scanf("%d",&x);
vec[i].push_back(x);
}
}
int ma=0,ma_id;
for(int i=2;i<=n;i++){
if(ma<cal(vec[1],vec[i])){
ma=cal(vec[1],vec[i]);
ma_id=i;
}
}
if(ma<=2){
printf("Yes\n");
pr(vec[1]);
}else if(ma>4){
printf("No\n");
}else if(3<=ma&&ma<=4){
vector<int> pos;
for(int j=1;j<=m;j++){ //把不同的位置放在pos里面
if(vec[1][j]!=vec[ma_id][j]){
pos.push_back(j);
}
}
for(int j=0;j<pos.size();j++){
for(int k=0;k<pos.size();k++){
if(j==k) continue;
vector<int> temp=vec[1];
temp[pos[j]]=vec[ma_id][pos[j]];
temp[pos[k]]=-1;
check(temp);
}
}
printf("No\n");
}
return 0;
}