RT,大概的思路是把每辆车超速的区间计算出来,放进优先队列里面,左端点右端点分开放入。 枚举每一个测速仪,贪心找到一个测速仪左边没有右端点,而下一个测速仪的左边有右端点时,该测速仪一定会被选择。 vis 代码可读性高,求调,万分感谢!!!
#include<bits/stdc++.h>
#define endl "\n"
#define PII pair<double,int>
#define fir first
#define sec second
#define mk make_pair
using namespace std;
const int N=1e5+100;
const int Inf=1e9;
int T;
int n,m,V,L,st,ans1,ans2;
int d[N],v[N],a[N];
int p[N];
int vis[N]; // 用以保存车是否已被判断完
priority_queue<PII,vector<PII>,greater<PII> > ql,qr;
struct node{
double l,r;
}q[N];
void CE(){
ans1=ans2=0;
while(ql.size()) ql.pop();
while(qr.size()) qr.pop();
memset(vis,0,sizeof vis);
}
int main(){
// freopen("detect4.in","r",stdin);
// freopen("1.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>T;
while(T--){
CE();
cin>>n>>m>>L>>V;
for(int i=1;i<=n;++i) {
cin>>d[i]>>v[i]>>a[i];
PII tl,tr;
if(a[i]==0) {
if(v[i]<=V) continue;
tl.fir=d[i];
tr.fir=L+1e-10;
tl.sec=tr.sec=i;
}
else if(a[i]>0){
double l=((double)(V*V-v[i]*v[i])/2.0/(a[i]*1.0));
l=max(0.0,l);l=l+d[i]*1.0;
if(l>=(double)L) continue;
tl.fir=l+1e-10;
tr.fir=L+1e-10;
tl.sec=tr.sec=i;
}
else {
if(v[i]<=V) continue;
tl.fir=d[i];
double r=(d[i]*1.0+(double)(V*V-v[i]*v[i])/2.0/(a[i]*1.0));
r-=1e-10;
r=min(r,L*1.0+1e-10);
tr.fir=r;
tl.sec=tr.sec=i;
}
ql.push(tl);
qr.push(tr);
}
for(int i=1;i<=m;++i) cin>>p[i];
sort(p+1,p+1+m);
for(int i=1;i<=m;++i){
while(qr.size()&&(vis[qr.top().sec]||qr.top().fir<=(double)p[i])){
if(qr.top().fir<=p[i]) vis[qr.top().sec]=1;
qr.pop();
}
while(i+1<=m&&(double)p[i+1]<=qr.top().fir) ++i; //贪心向右找最后一个左边没有右端点的测速仪
if(!ql.size()||!qr.size()) break;
++ans2;
while(ql.size()&&(ql.top().fir<=(double)p[i]||vis[ql.top().sec])) {
if(vis[ql.top().sec]) {
ql.pop();
continue;
}
++ans1;
vis[ql.top().sec]=1;
ql.pop();
}
}
cout<<ans1<<' '<<m-ans2*(ans1?1:0)<<endl;
}
return 0;
}