题解:P17380 [PacNW 2025] Bus Seating

题目链接

思路

先说一个结论:任意时刻都最多只有 \(\log C\) 种不同人数的座位。


证明

设当前乘客最喜欢第 \(x\) 排,\(y,z\)\(y<z\))两排座位分别坐了 \(p_y,p_z\) 个人,则选 \(x\) 更优当且仅当:

\[\frac{C-|x-y|}{2^{p_y}}\geq \frac{C-|x-z|}{2^{p_z}} \]

转换一下:

\[\frac{C-|x-y|}{C-|x-z|}\geq 2^{p_y-p_x} \]

左式的最大值为 \(\frac{C}{C-n+1}\leq C\),而右式在 \(p_y-p_x\geq \log C\) 时会大于 \(C\)。也就是说,当两排座位坐的人数相差过大时,人数少的座位一定会优于人数多的座位。假设任意时刻满足 \(p_{\max}-p_{\min}\geq \log C\),那后面的乘客一定会在选 \(p_{\max}\) 对应的座位前把 \(p_{\min}\) 对应的座位选完,差值只减不增。这样就能保证 \(p_{\max}-p_{\min}\leq \log C\)


有了这个结论后,看似暴力的做法就可以通过了。对每种人数开一个 set,存储所有是这个人数的座位编号。每次查询就从每个里面有元素的 set 中找到离 \(a_i\) 最近的座位,乘上相应的权值后取最大值即可。

时间复杂度 \(O(m\log C \log n)\)

代码

#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define int long long
const int N=2e5+5;

int n,k,m,c,l,r;
set<int> p[N];
struct maxv
{
    int p,v,h;
    bool operator>(maxv x)
    {
        return v==x.v?p<x.p:v>x.v;
    }
};

maxv max(maxv x,maxv y)
{
    return x>y?x:y;
}

signed main()
{
    scanf("%lld%lld%lld%lld",&n,&k,&m,&c);
    for(int i=1;i<=n;i++)
        p[0].insert(i);
    for(int i=1;i<=m;i++)
    {
        int x;
        maxv mx={0,0,0};
        scanf("%lld",&x);
        for(int j=l;j<=r;j++)
            if(p[j].size())
            {
                set<int>::iterator it;
                if(x<=*p[j].begin())
                    it=p[j].begin();
                else if(x>=*prev(p[j].end()))
                    it=prev(p[j].end());
                else
                {
                    it=p[j].lower_bound(x);
                    if(*it-x>=x-*prev(it))
                        it--;
                }
                mx=max(mx,{*it,(c-abs(*it-x))*(1ll<<(r-j)),j});
            }
        printf("%lld ",mx.p);
        p[mx.h].erase(mx.p);
        p[mx.h+1].insert(mx.p);
        if(p[l].empty())
            l++;
        if(r<k-1&&p[r+1].size())
            r++;
    }
    return 0;
}
posted @ 2026-09-03 19:37  ShanLing3  阅读(7)  评论(0)    收藏  举报
//雪花飘落效果