【题意】

有n个球和m个篮子,将球依次放进篮子里,优先放到球最少的篮子里,如果有多个这样的,则放到这样的篮子中,放到Codeforces Round #123 (Div. 2) B - After Training_子树值最小的那个篮子中。问每个球分别放到了哪个篮子中。

【解题方法】

特别注意的一个细节,Codeforces Round #123 (Div. 2) B - After Training_子树是一个实数,如果存到一个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;
}