1 条题解

  • 0
    @ 2026-9-23 22:09:54

    模拟题,有良心搬题人把这题放到了 NOI 模拟赛 T1 创飞了一车人。

    维护以下事件:

    1. ii 与 i+1i+1 相撞。
    2. 你的车与 ii 相撞。

    将车视为若干连续段,当出现事件 11 时,修改 ii 所在连续段头部的车速,当出现事件 22 时,判断一下是否会进行超车即可。

    注意精度,可能需要使用 __float128。

    #include<bits/stdc++.h>
    using namespace std;
    #define ld __float128
    #define int long long 
    /*
    op=1 pos 与 pos+1 相邻碰撞
    op=2 跑车追上 pos 车尾 
    */
    const ld eps=1e-24L;
    struct Event{
    	int op,pos;
    	ld tim;
    	bool operator <(const Event &b) const{
    		if(tim!=b.tim) return tim>b.tim;
    		if(op!=b.op) return op>b.op;
    		return pos>b.pos;
    	}
    };
    ld Abs(ld x){
    	if(x<0) return -x;
    	return x;
    }
    #define fabs Abs
    bool Eq(Event x,Event y){
    	return x.op==y.op&&x.pos==y.pos&&x.tim==y.tim;
    }
    struct delpq{
    	priority_queue<Event> Q,Del;
    	void push(Event x){
    		Q.push(x);
    	}
    	void pop(){
    		Q.pop();
    	}
    	void del(Event x){
    		Del.push(x);
    	}
    	Event top(){
    		while(!Del.empty()&&!Q.empty()){
    			if(Eq(Del.top(),Q.top())){
    				Del.pop();
    				Q.pop();
    			}else break;
    		}
    		assert(!Q.empty());
    		return Q.top();
    	}
    	bool empty(){
    		while(!Del.empty()&&!Q.empty()){
    			if(Eq(Del.top(),Q.top())){
    				Del.pop();
    				Q.pop();
    			}else break;
    		}
    		return Q.empty();
    	}
    }Q;
    struct Car{
    	int x,d,w,m;
    	ld v;
    }a[100005];
    int n,D,W,M;
    ld V;
    Event e[3][100005];
    ld nowTime=0;
    ld lstPos[100005],lstTime[100005];//上一次被修改车速的时间和位置
    ld GetPos(int id){//获得车头位置 
    	return lstPos[id]+(nowTime-lstTime[id])*a[id].v; 
    }
    ld NowPos(){
    	return nowTime*V;//跑车始终匀速 
    }
    void addEvent(int op,int pos){
    	if(e[op][pos].op<0) return;
    	Q.push(e[op][pos]);
    }
    void delEvent(int op,int pos){
    	if(e[op][pos].op<0) return;
    	Q.del(e[op][pos]);
    }
    int isDel[100005];
    int lstDel[100005];
    int fd(int x){
    	if(lstDel[x]==x) return x;
    	return lstDel[x]=fd(lstDel[x]);
    }
    void updData(int pos){//pos 车速改变 
    	//pos车速等于pos+1车速
    	//影响pos-1追pos和跑车追pos
    	if(pos-1>=1&&e[1][pos-1].op!=-2){
    		ld dis=GetPos(pos)-a[pos].d-GetPos(pos-1);
    		delEvent(1,pos-1);
    		if(a[pos-1].v>a[pos].v+eps){
    			e[1][pos-1].op=1;
    			e[1][pos-1].pos=pos-1; 
    			e[1][pos-1].tim=nowTime+(dis/(a[pos-1].v-a[pos].v)); 
    			addEvent(1,pos-1);
    		}else e[1][pos-1].op=-1;
    	}
    	if(e[2][pos].op!=-2){
    		ld dis=GetPos(pos)-a[pos].d-NowPos();
    		delEvent(2,pos);
    		e[2][pos].tim=nowTime+(dis/(V-a[pos].v));
    		if(e[2][pos].tim<nowTime-eps) e[2][pos].tim=nowTime;
    		addEvent(2,pos);
    	}
    }
    signed main(){
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	cout.tie(0);
    	cin>>n>>D>>W>>M;
    	V=(ld)W/(ld)M;
    	for(int i=1;i<=n;i++){
    		lstDel[i]=i;
    		cin>>a[i].x>>a[i].d>>a[i].w>>a[i].m;
    		a[i].v=(ld)a[i].w/(ld)a[i].m;
    	}
    	for(int i=1;i<n;i++){
    		ld dis=a[i+1].x-a[i].x-a[i+1].d;
    		assert(dis>-eps);
    		if(a[i].v>a[i+1].v+eps){
    			e[1][i].op=1;
    			e[1][i].pos=i;
    			e[1][i].tim=(dis/(a[i].v-a[i+1].v)); 
    			addEvent(1,i);
    		}else e[1][i].op=-1;
    	}
    	for(int i=1;i<=n;i++){
    		lstPos[i]=a[i].x;
    		lstTime[i]=0;
    		ld dis=a[i].x-a[i].d;
    		e[2][i].op=2,e[2][i].pos=i;
    		e[2][i].tim=(dis/(V-a[i].v));
    		addEvent(2,i);
    	}
    	#define RIGHT 0
    	#define LEFT 1
    	int ans=0;
    	int nowSide=RIGHT;
    	//isDel_x 表示 x 是否被撞 
    	while(!Q.empty()){
    		auto E=Q.top();
    		e[E.op][E.pos].op=-2;
    		Q.pop();
    		nowTime=E.tim; 
    		if(E.op==1){
    			isDel[E.pos+1]=1;
    			lstDel[E.pos+1]=fd(E.pos); 
    			int id=fd(E.pos);
    			if(id>0){
    				lstPos[id]=GetPos(id);
    				lstTime[id]=nowTime;
    				a[id].v=a[E.pos+1].v;
    				updData(id);
    			}
    		}else{
    			if(isDel[E.pos]) continue; 
    			if(nowSide==RIGHT) ans++,nowSide=LEFT;
    			else if(E.pos==1||GetPos(E.pos-1)<=NowPos()-D+eps) ans++;
    		}
    	}
    	cout<<ans<<"\n"; 
    	return 0;
    }
    
    • 1

    信息

    ID
    7136
    时间
    1500ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者