题解:P16558 [ICPC 2026 LAC] Late and Disobedient
lailai0916 · · 题解
题意简述
有
询问时刻递增,询问数可达
解题思路
逐次询问排序行人位置需要
只需考虑以下两类位置作为空隙左端点:线段左端点
因为任何合法空隙都可以向左扩展,直到碰到最近的行人或边界
加入一个位置始终为
这是关于
行人
所有初始位置、速度和询问时刻都是整数,因此行人位置也是整数。严格不等式可以精确地改写为闭区间条件:
由此得到行人
对固定的
具体维护第一个尚未处理的时刻 pos 表示。遇到禁止区间
这样得到的每个时间区间都有一个确定的合法左端点,因此不会产生误判;而任何可以通过的时刻至少有一个前述左端点,也必定出现在某个可行区间中,所以没有遗漏。
代码用 get 将条件
C++ 的整数除法向
将所有左端点产生的可行时间区间汇总,按左端点排序。询问时刻递增,可以用一个指针跳过右端点小于当前时刻的区间。剩余的第一个区间若左端点不大于询问时刻,则回答 Y,否则回答 N。不必预先合并重叠区间:被跳过的区间不可能覆盖当前或之后的询问,而其余区间的左端点只会更大。
每个左端点至多产生
参考代码
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using pll=pair<ll,ll>;
const int N=1005;
ll x[N],v[N];
void get(ll x,ll v,ll a,ll b,ll &l,ll &r)
{
if(v<0)
{
x=-x;
v=-v;
ll t=a;
a=-b;
b=-t;
}
if(!v)
{
if(x<a||x>b)l=1,r=0;
return;
}
l=max(l,(a-x)/v+((a-x)%v>0));
r=min(r,(b-x)/v-((b-x)%v<0));
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n,c,len;
cin>>n>>c>>len;
for(int i=1;i<=n;i++)cin>>x[i]>>v[i];
vector<pll> a;
for(int i=0;i<=n;i++)
{
ll l=0,r=1000000000;
get(x[i],v[i],0,len-c,l,r);
if(l>r)continue;
vector<pll> b;
for(int j=1;j<=n;j++)
{
ll u=l,w=r;
get(x[j]-x[i],v[j]-v[i],1,c-1,u,w);
if(u<=w)b.push_back({u,w});
}
sort(b.begin(),b.end());
ll pos=l;
for(auto t:b)
{
if(pos<t.first)a.push_back({pos,t.first-1});
pos=max(pos,t.second+1);
}
if(pos<=r)a.push_back({pos,r});
}
sort(a.begin(),a.end());
int q;
cin>>q;
int pos=0;
while(q--)
{
ll t;
cin>>t;
while(pos<a.size()&&a[pos].second<t)pos++;
cout<<(pos<a.size()&&a[pos].first<=t?'Y':'N')<<'\n';
}
return 0;
}