版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
先呈上原题链接
题意:
在大学里选修过数据结构的同学大部分都知道
算法的线性探查法:
假设有一个元素互不相同的正整数数组 ,我们用以下方法得到数组 :
初始时 都为 ,我们对 依次插入 ,假设现在要插入的数是 ,首先我们找到 这个位置,如果 ,则令 ,之后结束这次插入;否则看 是否等于 ,如果等于则令 ,如果不等于,则继续看 ,直到找到一个位置。
完成所有插入后,我们会得到一个数组 ,现在给定这个数组 ,你需要求一个字典序最小的
思路:
- 首先我们知道,如果某个数 hash后应该在位置 ,但 的实际位置却是在数组 的 位置,那么 时, 到 里面这些数都是在 插入之前插入的; 时, 到 和 到 里面这些数都是在 插入之前插入的。
- 当我们知道某个数 一定是在 之前插入的,我们就可以从 到 连一条有向边。然后该图得到的拓扑序列通过线性探测法一定能得到数组 。
- 最后一步就是如何得到字典序最小。只需要在拓扑排序的时候用一个优先队列,让所有入度为零的节点的最小的那个值排最前面就行了。
坑点:
无
good luck and have fun!!!
附上代码:
#include<bits/stdc++.h>
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define test(flag,value) cout<<flag<<":"<<(value)<<endl
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int INF=0x3f3f3f3f;
const int MAXN=1e3+10;
const int MOD=998244353;
const double PI=acos(-1);
int n;
map<int,int> M;
vector<int> G[MAXN];
int in[MAXN];
int b[MAXN];
int ans[MAXN];
void topo()
{
priority_queue<int,vector<int>,greater<int> >Q;
for(int i=0;i<n;i++)
if(in[i]==0)
Q.push(b[i]);
int cnt=0;
while(!Q.empty())
{
int val=Q.top();Q.pop();//取优先队列里值最小的
ans[cnt++]=val;
int node=M[val];
int sz=G[node].size();
for(int i=0;i<sz;i++)
{
int x=G[node][i];
in[x]--;
if(in[x]==0)
Q.push(b[x]);
}
}
}
int main(void)
{
scanf("%d",&n);
mem(in,0);
for(int i=0;i<n;i++)
{
scanf("%d",b+i);
M[b[i]]=i;//离散化
}
for(int i=0;i<n;i++)
{
int tmp=b[i];
int pos=tmp%n;
if(pos<i)
{
for(int j=pos;j<i;j++)
{
G[j].pb(i);
in[i]++;
}
}
else if(pos>i)
{
for(int j=0;j<i;j++)
{
G[j].pb(i);
in[i]++;
}
for(int j=pos;j<n;j++)
{
G[j].pb(i);
in[i]++;
}
}
}
topo();
for(int i=0;i<n;i++)
{
if(i==0)
printf("%d", ans[i]);
else
printf(" %d", ans[i]);
}
}