https://www.nowcoder.com/acm/contest/142/J
题意:
给你一个n,和n个空位。如果你得到一个x,就把x填在x%n这个位子。如果x%n被填了,就到(x+1)%n,反复。
现在给你n个已经被填好的位子。让你求出字典序最小的入座次序。
POINT:
用一个优先队列。如果序列里的x的位子就是x%n,证明这个数是最开始就放好的。加入优先队列。
每次出一个最小元素。把它填入位子a,然后用并查集把a和a+1合并,看看现在a的祖先能不能被加入队列。
就这样反复。
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
const int maxn=2e5+7;
int fa[maxn];
struct node
{
int val,pos;
node(int x,int y)
{
val=x;pos=y;
}
bool friend operator < (node a,node b)
{
return a.val>b.val;
}
};
int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
}
int vis[maxn];
int cnt,num;
int ans[maxn];
int a[maxn];
int main(){
priority_queue<node> q;
int T,n;
scanf("%d",&T);
while(T--){
cnt=num=0;
scanf("%d",&n);
for(int i=0;i<n;i++){
fa[i]=i;
scanf("%d",&a[i]);
vis[i]=0;
if(a[i]==-1) continue;
if(a[i]%n==i){
q.push(node(a[i],i));
vis[i]=1;
}
num++;
}
while(!q.empty()){
node x=q.top();
q.pop();
ans[++cnt]=x.val;
int to=fa[find(x.pos)]=find((x.pos+1)%n);
if(vis[to]||a[to]==-1||find(a[to]%n)!=to) continue;
q.push(node(a[to],to));
vis[to]=1;
}
if(cnt<num){
printf("-1\n");
}else{
for(int i=1;i<=cnt;i++){
printf("%d",ans[i]);
if(i!=cnt) printf(" ");
}
printf("\n");
}
}
return 0;
}