【题意】
有n个球和m个篮子,将球依次放进篮子里,优先放到球最少的篮子里,如果有多个这样的,则放到这样的篮子中,放到值最小的那个篮子中。问每个球分别放到了哪个篮子中。
【解题方法】
特别注意的一个细节,是一个实数,如果存到一个int里面,会造成错误的结果。这道题用线段树维护整个区间的最小值和最小值所在的位置。进行pushup的时候,如果左子树的最小值和右子树的最小值相等,就要将这个节点的最小值的位置就要进行比较维护。对于每一个球,输出当前最小值的位置,往最小值位置进行加1操作.
【AC 代码】
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100010;
struct node{
int l,r;
int minn,minp;
}Tree[maxn*4];
double MID;
void pushup(int rt)
{
Tree[rt].minn=min(Tree[rt*2].minn,Tree[rt*2+1].minn);
if(Tree[rt].minn==Tree[rt*2].minn) Tree[rt].minp=Tree[rt*2].minp;
else Tree[rt].minp=Tree[rt*2+1].minp;
if(Tree[rt*2+1].minn==Tree[rt].minn&&abs(Tree[rt].minp-MID)>abs(Tree[rt*2+1].minp-MID)){
Tree[rt].minp=Tree[rt*2+1].minp;
}
}
void Build(int l,int r,int rt)
{
Tree[rt].l=l,Tree[rt].r=r;
Tree[rt].minn=0;
if(l==r){
Tree[rt].minp=l;
return ;
}
int mid=(l+r)/2;
Build(l,mid,rt*2);
Build(mid+1,r,rt*2+1);
pushup(rt);
}
void update(int rt){
if(Tree[rt].l==Tree[rt].r){
printf("%d\n",Tree[rt].l);
Tree[rt].minn++;
return ;
}
int mid=(Tree[rt].l+Tree[rt].r)/2;
if(Tree[rt].minp<=mid) update(rt*2);
else update(rt*2+1);
pushup(rt);
}
int main()
{
int n,m;
cin>>n>>m;
MID=(m+1)/2.0;
Build(1,m,1);
for(int i=1; i<=n; i++) update(1);
return 0;
}