在第一问时计算出超速区间,第二问贪心策略是:按区间右端点排序,分开计算a>0和a=0时的超速区间(因为这种情况只需要一个监控就行),找到区间左端点的最大值。 然后计算a<0时的答案,定义一个mx,如果当前区间的左端点大于mx 就让ans2++(不能关闭的监控),更新mx=当前的区间右端点;赛时A,B的样例过了,有a<0的情况出错,都是只差1或2。现在也是赛时A,B过了但提交爆0。 现在不知道是二分找超速区间出错还是贪心策略有问题
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
struct qq{
int d,v,l,r,a;
}car[N];
int p[N];
int t;
int n,m,L,V;
bool check(int x,int po){
ll vmo=(car[po].a*2*(p[x]-car[po].d)+car[po].v*car[po].v);
if(vmo>V*V)return 1;
else return 0;
}
bool cmp(qq x,qq y){
if(x.r!=y.r)return x.r<y.r;
else return x.l<y.l;
}
int main(){
// freopen("detect4.in","r",stdin);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>t;
while(t--){
cin>>n>>m>>L>>V;
for(int i=1;i<=n;++i){
cin>>car[i].d>>car[i].v>>car[i].a;
car[i].l=car[i].r=n+10;
}
for(int i=1;i<=m;++i){
cin>>p[i];
}
int z=0,x=0,c=0;
int ans1=0;
for(int i=1;i<=n;++i){
if(car[i].d>p[m])continue;
if(car[i].a>0){
ll vmo=(car[i].a*2*(p[m]-car[i].d)+car[i].v*car[i].v);
if(vmo>V*V){
z++;
ans1++;
int l=1,r=m,mid;
while(l<r){
mid=(l+r+1)>>1;
if(check(mid,i))r=mid-1;
else l=mid;
}
car[i].l=l;
car[i].r=m;
}
}
else if(car[i].a<0){
int l=1,r=m,mid;
while(l<r){
mid=(l+r)>>1;
if(p[mid]>car[i].d)r=mid;
else l=mid+1;
}
ll vmo=(car[i].a*2*(p[l]-car[i].d)+car[i].v*car[i].v);
if(vmo>V*V){
ans1++;
x++;
car[i].l=l;
r=m;
while(l<r){
mid=(l+r+1)>>1;
if(check(mid,i))r=mid-1;
else l=mid;
}
car[i].r=l;
}
}
else{
if(car[i].v>V){
int l=1,r=m,mid;
while(l<r){
mid=(l+r)>>1;
if(p[mid]>car[i].d)r=mid;
else l=mid+1;
}
c++;
ans1++;
car[i].l=l;
car[i].r=m;
}
}
}
cout<<ans1<<" ";
sort(car+1,car+1+n,cmp);
int ans2=0;
if(car[1].l!=n+10){
int mi=0;
for(int i=1;i<=n;++i){
if(car[i].r==n+10)break;
if(car[i].a<0)continue;
mi=max(mi,car[i].l);
}
int mx=0;
bool cu=0;
for(int i=1;i<=n;++i){
if(car[i].r==n+10)break;
if(car[i].a>=0)continue;
if(!cu){
cu=1;
ans2++;
mx=car[i].r;
continue;
}
if(car[i].l>mx){
ans2++;
mx=car[i].r;
}
}
if(mx<mi)ans2++;
}
cout<<m-ans2<<"\n";
}
}