[CSP-S 2024] 超速检测——模拟、贪心
[CSP-S 2024] 超速检测(民间数据)
题目描述
小 D 新入职了某国的交管部门,他的第一个任务是负责国家的一条长度为 \(L\) 的南北主干道的车辆超速检测。为了考考小 D,上司首先需要他解决一个简化的场景。
这个周末,主干道上预计出现 \(n\) 辆车,其中第 \(i\) 辆车从主干道上距离最南端 \(d_i\) 的位置驶入,以 \(v_i\) 的初速度和 \(a_i\) 的加速度做匀加速运动向北行驶。我们只考虑从南向北的车辆,故 \(v_i > 0\),但 \(a_i\) 可正可负,也可以为零。当车辆行驶到主干道最北端(即距离最南端为 \(L\) 的位置)或速度降为 \(0\)(这只可能在 \(a_i < 0\) 时发生)时,我们认为该车驶离主干道。
主干道上设置了 \(m\) 个测速仪,其中第 \(j\) 个测速仪位于主干道上距离最南端 \(p_j\) 的位置,每个测速仪可以设置开启或关闭。当某辆车经过某个开启的测速仪时,若这辆车的瞬时速度超过了道路限速 \(V\),那么这辆车就会被判定为超速。注意当车辆驶入与驶出主干道时,如果在对应位置有一个开启的测速仪,这个测速仪也会对这辆车进行测速。
上司首先想知道,如果所有测速仪都是开启的,那么这 \(n\) 辆车中会有多少辆车被判定为超速。
其次,为了节能,部门想关闭一部分测速仪。然而,他们不希望漏掉超速的车,也就是说,当 \(n\) 辆车里的某辆车在所有测速仪都开启时被判定为超速,他们希望在关闭一部分测速仪以后它依然被判定为超速。上司还想知道在这样的条件下最多可以关闭多少测速仪。
由于 \(n\) 很大,上司允许小 D 使用编程解决这两个问题,于是小 D 找到了你。
如果你对于加速度并不熟悉,小 D 贴心地在本题的“提示”部分提供了有关加速度的公式。
分析
贪心
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100,M=1e6+100;
int n,m,l,lim;
int T,h[N],num,c[M];
bool w[N];
struct car
{
int d0,v0,jia;
}g[N];
struct rang
{
int x,y,id;
}r[N];
int lowbit(int x){return x&(-x);}
int que(int x)
{
int sum=0;
while(x)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
void upd(int x,int z)
{
while(x<=l)
c[x]+=z,x+=lowbit(x);
}
void init()
{
scanf("%d%d%d%d",&n,&m,&l,&lim);
++l;num=0;
for(int i=1;i<=l;++i)c[i]=0;
for(int i=1;i<=n;++i)
{
scanf("%d%d%d",&g[i].d0,&g[i].v0,&g[i].jia);
++g[i].d0;
}
for(int i=1;i<=m;++i)
{
scanf("%d",&h[i]);
//cout<<h[i]<<endl;
++h[i];upd(h[i],1);
}
for(int i=1;i<=n;++i)
{
if(g[i].jia==0)
{
if(g[i].v0>lim)
{
if(que(l)==que(g[i].d0-1))continue;
++num;
r[num].x=g[i].d0;
r[num].y=l;
r[num].id=num;
}
}
else if(g[i].jia>0)
{
if(g[i].v0>lim)
{
if(que(l)==que(g[i].d0-1))continue;
++num;
r[num].x=g[i].d0;
r[num].y=l;
r[num].id=num;
}
else
{
//v1^2-v0^2=2ax
double len=(lim*lim-g[i].v0*g[i].v0)*1.0/(2.0*g[i].jia);
int ri=min((int)ceil(len+g[i].d0),l+1);
if(ri<=l)
{
if(que(l)==que(ri-1))continue;
++num;
r[num].x=ri;
r[num].y=l;
}
}
}
else
{
if(g[i].v0<=lim)
continue;
double len=(lim*lim-g[i].v0*g[i].v0)*1.0/(2.0*g[i].jia);
int ri=min((int)floor(len+g[i].d0),l);
if(que(ri)==que(g[i].d0-1))continue;
++num;
r[num].x=g[i].d0;
r[num].y=ri;
}
}
}
bool cmp(rang a,rang b)
{
if(a.y==b.y)return a.x<b.x;
return a.y<b.y;
}
void work()
{
//for(int i=1;i<=num;++i)
//printf("%d %d\n",r[i].x,r[i].y);
printf("%d ",num);
sort(r+1,r+1+num,cmp);
int pos=0,ans=0;
for(int i=1;i<=num;++i)
{
if(r[i].x<=h[pos])
continue;
else
{
while(pos+1<=m && h[pos+1]<=r[i].y)
++pos;
++ans;
}
}
printf("%d\n",m-ans);
}
int main()
{
cin>>T;
while(T--)
{
init();
work();
}
return 0;
}
本文来自博客园,作者:Glowingfire,转载请注明原文链接:https://www.cnblogs.com/Glowingfire/p/18514346