tokitsukaze and Hash Table
theme:给定n个数,按hash方式依次插入从0~n-1的格子里,具体为如果x%n位上还没有填上数,则插入x,否则依次往后找到第一个空位置插入x.输出每个位置上的数。1≤n≤10^6,0≤x≤10^9
solution:直接暴力的话很可能超时o(n^2),考虑用并查集维护空位置,对于每个数x,将它插入idx=Find(x%n)的位置,再合并idx与idx+1
这题如果n的范围是1e5左右的话可以考虑用set做,因为set会自动排序且插入删除时间复杂度都为o(logn)
//并查集模拟hash地址冲突
#include<bits/stdc++.h>
#define far(i,s,n) for(int i=s;i<n;++i)
typedef long long ll;
using namespace std;
int fa[1000010];
int ans[1000010];
void init(int n)
{
far(i,0,n)
fa[i]=i;
}
int Find(int x)
{
return fa[x]==x?x:fa[x]=Find(fa[x]);
}
void unit(int x,int y)
{
x=Find(x);
y=Find(y);
fa[x]=y;
}
int main()
{
int n;
cin>>n;
init(n);
far(i,0,n)
{
int x;
scanf("%d",&x);
int mod=x%n;
int idx=Find(mod);
ans[idx]=x;
unit(idx,(idx+1)%n);
}
far(i,0,n)
printf("%d ",ans[i]);
puts("");
return 0;
}
C、tokitsukaze and Soldier
theme:从n个人里选出若干个人要求战斗力最大,每个人有两个属性v表示战斗力,s表示选了他的话就会限制最多选s个人,问最大能选出战斗力为多少的团队?1<=s<=n<=1e5,1<=v<=1e9
solution:枚举最终选出的团队人数是以谁的s为上限的,即团队人数=si时最大战斗力。既然是以si为上限,说明团队中其他人的s值都>=si,所以我们现将这n个人按s值排序,在s值>=si的情况下,我们当然优先选v值大的人凑满si个人,所以我们用一个优先队列来几=记录,每遍历到一个si就出队v值小的直到队列大小<si,再讲vi入队,每次出队都更新以si为上界的答案。
#include<bits/stdc++.h>
using namespace std;
#define far(i,t,n) for(int i=t;i<n;++i)
#define pk(a) push_back(a)
#define lowbit(x) x&(-x)
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int inf=0x3f3f3f3f;
struct _a
{
int s;
ll v;
bool operator<(_a b)const
{
if(s==b.s)
return v>b.v;
return s>b.s;
}
}a[100010];
priority_queue<ll,vector<ll>,greater<ll> >q;
int main()
{
int n;
cin>>n;
far(i,0,n)
scanf("%lld%d",&a[i].v,&a[i].s);
sort(a,a+n);
ll ans=0,maxx=0;
far(i,0,n)
{
while(q.size()>=a[i].s)
{
maxx-=q.top();
q.pop();
}
maxx+=a[i].v;
q.push(a[i].v);
ans=max(ans,maxx);
}
cout<<ans<<endl;
}