PTA 逆散列问题 (30 分)(贪心)

题目链接:https://pintia.cn/problem-sets/1107178288721649664/problems/1107178432099737614

题目大意:

给定长度为 N 的散列表,处理整数最常用的散列映射是 (。如果我们决定用线性探测解决冲突问题,则给定一个顺序输入的整数序列后,我们可以很容易得到这些整数在散列表中的分布。例如我们将 1、2、3 顺序插入长度为 3 的散列表HT[]后,将得到HT[0]=3HT[1]=1HT[2]=2的结果。

但是现在要求解决的是“逆散列问题”,即给定整数在散列表中的分布,问这些整数是按什么顺序插入的?

我的理解:对于当前的数,先看他%n是多少,如果这个位上没有数,那么就把这个数放在这个位置,如果已经存在,就从当前的这个数的位置往后找,直到有空缺的时候停(如果到了最后一个还没有找到,那么再从第一个位置开始找)。

具体思路:首先对数组排一下序,因为我们要求的是字典序最小,那么我们先看第一个数是不是合法的,如果合法,就直接输出。否则,再去找第二小的数,以此类推。

然后再加两个标记数组,标记当前的数是不是用过了,以及当前的位置是否有数存在就可以了。

感谢剑锋学长和张明学长的帮忙┗( ▔, ▔ )┛

AC代码:

 #include <bits/stdc++.h>
using namespace std;
# define ll long long
const int maxn = 2e5+;
int a[maxn],b[maxn];
int ans[maxn];
int pos[maxn],vis[maxn];
int viss[maxn];
int main()
{
int n;
scanf("%d",&n);
int tot=;
for(int i=; i<n; i++)
{
scanf("%d",&a[i]);
if(a[i]>=){
b[tot++]=a[i];
}
}
int tmp=,flag;
sort(b,b+tot);
for(int i=; i<tot; i++){
for(int j=; j<tot; j++){
if(vis[j])//当前的数已经用过了,就不需要再找了
continue;
flag=;
for(int k=b[j]%n;;){
if(viss[k]==&&b[j]==a[k]){
vis[j]=;
viss[k]=;
ans[i]=b[j];
flag=;
break;
}
if(viss[k]==){
break;
}
k++;
if(k==n)
k=;
}
if(!flag)
break;
}
}
for(int i=; i<tot; i++){
if(i==)
printf("%d",ans[i]);
else
printf(" %d",ans[i]);
}
printf("\n");
return ;
}
上一篇:Codefroces A. Saitama Destroys Hotel


下一篇:SPOJ DQUERY D-query(主席树)