Benelux Algorithm Programming Contest 2016 Preliminary I. Rock Band
题意:
给出一个n*m的矩阵
每一行的每个数<=m且不重复
在其中找一个最小的n*s子矩阵,使得该子矩阵里,每一行的数字集合都是相同的
在前s列每一行数字集合都是相同的,相当于在前s列的每个数都出现了n次
所以一列一列的扫每个数,第一行的加入
每有一个数出现n次就删走这个数
直至为空
#include<cstdio> #include<vector> #include<algorithm> using namespace std; #define N 1000001 vector<int>v[N]; int s[N],a[N]; int main() { int n,m,x; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) { scanf("%d",&x); v[i].push_back(x); } int y=0,i; for(i=0;i<m;++i) { y++; for(int j=1;j<=n;++j) { s[v[j][i]]++; if(s[v[j][i]]==n) y--; } if(!y) break; } printf("%d\n",i+1); for(int j=1;j<=i+1;++j) a[j]=v[1][j-1]; sort(a+1,a+i+2); for(int j=1;j<=i+1;++j) printf("%d ",a[j]); }
没有将每一行数字集合相同转化为出现次数
用并查集做的
依据第一行的数,后面几行每个数的父亲指向它前面最后一个没有出现的位置,直至该位置变为0
但不知为啥MLE了。。
此坑待填
#include<cstdio> #include<vector> #include<algorithm> using namespace std; #define N 1000001 vector<int>dy[N]; int a[N]; vector<int>fa[N]; int find(int j,int i) { return fa[j][i]==i ? i : fa[j][i]=find(j,fa[j][i]); } int main() { freopen("008-een-02.in","r",stdin); int n,m,x; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) { scanf("%d",&x); dy[x].push_back(j); if(i==1) a[j]=x; } for(int i=1;i<=n;++i) for(int j=0;j<=m;++j) fa[i].push_back(j); int p; int ans; bool tag; for(int i=1;i<=m;++i) { for(int j=1;j<=n;++j) { p=dy[a[i]][j-1]; fa[j][p]=find(j,fa[j][p-1]); } tag=true; for(int j=1;j<=n && tag;++j) if(find(j,fa[j][i])) tag=false; if(tag) { ans=i; break; } } sort(a+1,a+ans+1); printf("%d\n",ans); for(int i=1;i<=ans;++i) printf("%d ",a[i]); }