D:Cow Photography II
题意:
n头牛(n<=20000),有一个隐藏序列。
题目提供五个序列,都是从隐藏序列变化过来,每次可能有0头或多头牛会移动,但在五个序列中,每头牛最多只能移动一次,要求还原最初的隐藏序列。
思路:
因为每头牛最多只会移动一次,所以任意两头牛的先后次序最多只会改变两次,所以在五张照片中,序号在前面多的牛,排在前面。
根据复杂度我们可以通过sort+重写比较函数来n logn地还原隐藏序列。
这道题在比赛中做了好久,一个半小时都没做出来。想到了依靠先后次序关系,想着拓扑序建图的,可惜复杂度不够,就没想到这个cmp的方法。
遇到过好几次了,可恶、
int n,m;
int s[6][20060];
int p[20060];
vector<int>v;
int find(int x){
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
int id[20060];
bool cmp(int x,int y){
int cnt=0;
for(int i=1;i<=5;i++)
{
if(s[i][x]<s[i][y])cnt++;
}
return cnt>=3;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
v.push_back(p[i]);
id[i]=i;
}
sort(v.begin(),v.end());
for(int i=1;i<=n;i++){
s[1][find(p[i])]=i;
}
for(int i=2;i<=5;i++){
for(int j=1;j<=n;j++){
int a;
scanf("%d",&a);
s[i][find(a)]=j;
}
}
sort(id+1,id+1+n,cmp);
for(int i=1;i<=n;i++){
printf("%d\n",v[id[i]-1]);
}
return 0;
}