题解: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;
}

浙公网安备 33010602011771号