牛客练习赛50 B tokitsukaze and Hash Table
题目::
链接:https://ac.nowcoder.com/acm/contest/1080/B
tokitsukaze有n个数,需要按顺序把他们插入哈希表中,哈希表的位置为0到n-1。
插入的规则是:
刚开始哈希表是空的。
对于一个数x,在哈希表中,如果(x mod n)的位置是空的,就把x放在(x mod n)的位置上。如果不是空的,就从(x mod n)往右开始找到第一个空的位置插入。若一直到n-1都不是空 的,就从位置0开始继续往右找第一个空的位置插入。
因为哈希表总共有n个空位,需要插入n个数,所以每个数都能被插入。
现在tokitsukaze想知道把这n个数按顺序插入哈希表后,哈希表中的每个位置分别对应的是哪个数。
输入::
第一行包含一个正整数n(1≤n≤10^6)。
第二行包含n个非负整数x(0≤x≤10^9),这些数按从左到右的顺序依次插入哈希表。
输出::
输出一行,n个数,第i个数表示哈希表中位置为i所对应的数。(0≤i≤n-1)
样例1::
4 1 2 6 5
样例2::
4 3 0 7 11
分析::
普通思路走一次搜一次必定TLE;那我们可以优化一下二分来写,这就很好的想到了set 容器;
首先预处理将0~n-1插入进set中,对于输入的数据做处理,利用lower_bound函数可以快速找到第一个空位置,并将它删除;当返回的是end()是则需更改成s.begin();并且删除;
这里返回的迭代器所代表的值即是安放的位置,可以开个数组来存储;
详细见代码::
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll MOD=998244353; 5 const int maxn=1e6+10; 6 int ma[maxn]; 7 set<int>s; 8 int main() 9 { 10 s.clear(); 11 int n; 12 scanf("%d",&n); 13 for(int i=0;i<n;i++){ 14 s.insert(i); 15 } 16 for(int i=1;i<=n;i++){ 17 int x,k; 18 scanf("%d",&x); 19 int ans=x; 20 x%=n; 21 set<int>::iterator it; 22 it=s.lower_bound(x); 23 if(it!=s.end()){ 24 k=*it; 25 s.erase(it); 26 } 27 else{ 28 it=s.begin(); 29 k=*it; 30 s.erase(it); 31 } 32 ma[k]=ans; 33 } 34 for(int i=0;i<n;i++){ 35 if(i==0){ 36 printf("%d",ma[i]); 37 } 38 else{ 39 printf(" %d",ma[i]); 40 } 41 } 42 return 0; 43 }
本人此题还有解法
类似并查集 (也不能这样说,-_- )
分析::
首先也是预处理记录 0~n-1,然后通过找祖宗找到空位置
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll MOD=998244353; 5 const int maxn=1e6+10; 6 int ma[maxn]; 7 int f[maxn]; 8 int getfather(int x) 9 { 10 return x==f[x]?x:f[x]=getfather(f[x]); 11 } 12 int main() 13 { 14 int n; 15 scanf("%d",&n); 16 for(int i=0;i<n;i++){ 17 f[i]=i; 18 } 19 for(int i=1;i<=n;i++){ 20 int x,y; 21 scanf("%d",&x); 22 y=x; 23 x=getfather(x%n); 24 ma[x]=y; 25 f[x]=(x+1)%n;//更改已被占的位置并指向后面第一个空位置 26 } 27 for(int i=0;i<n;i++){ 28 if(i==0){ 29 printf("%d",ma[i]); 30 } 31 else{ 32 printf(" %d",ma[i]); 33 } 34 } 35 return 0; 36 }
纵使单枪匹马,也要勇闯天涯