N多校2018d3t10 Hash Function

理解hash过程

首先可知,先放进去肯定是h[i]%n==i的位置,这些个位置放进set按照字典序顺序来,然后每安排一个这样点,对于它后一位的值,如果还没被放入set,则如果它%对应的位置已经放入set了则它放入set ~

ac代码:

#include <bits/stdc++.h>
using namespace std;
#define per(i,a,b) for(int i=a;i<b;i++)
#define MP make_pair
typedef pair<int,int> PII;
typedef vector<int> VI;
const int inf =0x3f3f3f;
#define siz 200005
int n,h[siz],f[siz];//f[i]表示i位置现在要考虑的点位置
bool vis[siz];
void init()
{
    memset(vis,false,sizeof(vis));
    per(i,1,n)f[i]=i;
}
int Find(int u){return f[u]==u?u:f[u]=Find(f[u]);}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        init();
        set<PII>st;//带排序功能嘛
        per(i,0,n){scanf("%d",&h[i]);if(h[i]==-1)vis[i]=true;}
        per(i,0,n)f[i]=i;
        per(i,0,n){
            if(vis[i])continue;
            if(h[i]%n == i){st.insert(MP(h[i],i));vis[i]=true;}
        }
        VI ans;
        while(!st.empty()){
            auto tmp=*st.begin();
            st.erase(st.begin());
            ans.push_back(tmp.first);
            assert(Find(tmp.second)==tmp.second);//表示这个点上一步刚处理
            f[tmp.second]=Find((tmp.second+1)%n);
            if(f[tmp.second]!=tmp.second){
                int to=f[tmp.second];
                if(vis[to]==false&&Find(h[to]%n)==to){
                    vis[to]=true;
                    st.insert(MP(h[to],to));
                }
            }
        }
        bool flag=true;
        per(i,0,n)if(vis[i]==false){flag=false;break;}
        if(!flag)puts("-1");
        else {
            if(ans.empty())puts("");
            else{
                per(i,0,(int)ans.size())printf("%d%c",ans[i]," \n"[i==(int)ans.size()-1]);
            }
        }
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/WindFreedom/p/9385303.html