[CSP-S 2024] 超速检测——模拟、贪心
[CSP-S 2024] 超速检测(民间数据)
题目描述
小 D 新入职了某国的交管部门,他的第一个任务是负责国家的一条长度为 的南北主干道的车辆超速检测。为了考考小 D,上司首先需要他解决一个简化的场景。
这个周末,主干道上预计出现 辆车,其中第 辆车从主干道上距离最南端 的位置驶入,以 的初速度和 的加速度做匀加速运动向北行驶。我们只考虑从南向北的车辆,故 ,但 可正可负,也可以为零。当车辆行驶到主干道最北端(即距离最南端为 的位置)或速度降为 (这只可能在 时发生)时,我们认为该车驶离主干道。
主干道上设置了 个测速仪,其中第 个测速仪位于主干道上距离最南端 的位置,每个测速仪可以设置开启或关闭。当某辆车经过某个开启的测速仪时,若这辆车的瞬时速度超过了道路限速 ,那么这辆车就会被判定为超速。注意当车辆驶入与驶出主干道时,如果在对应位置有一个开启的测速仪,这个测速仪也会对这辆车进行测速。
上司首先想知道,如果所有测速仪都是开启的,那么这 辆车中会有多少辆车被判定为超速。
其次,为了节能,部门想关闭一部分测速仪。然而,他们不希望漏掉超速的车,也就是说,当 辆车里的某辆车在所有测速仪都开启时被判定为超速,他们希望在关闭一部分测速仪以后它依然被判定为超速。上司还想知道在这样的条件下最多可以关闭多少测速仪。
由于 很大,上司允许小 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
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程