1 条题解
-
0
模拟题,有良心搬题人把这题放到了 NOI 模拟赛 T1 创飞了一车人。
维护以下事件:
- 与 相撞。
- 你的车与 相撞。
将车视为若干连续段,当出现事件 时,修改 所在连续段头部的车速,当出现事件 时,判断一下是否会进行超车即可。
注意精度,可能需要使用
__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
- 上传者