发表文章

[最新] 牛客网暑期ACM多校训练营(第四场) - J Hash Function (并查集)

mrtreeeee 2月前 51

http://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;
}

 

相关推荐
最新评论 (0)
返回
发表文章
mrtreeeee
文章数
498
评论数
0
注册排名
699000