[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;
}






posted @ 2024-10-29 21:22  Glowingfire  阅读(113)  评论(2编辑  收藏  举报