基本思路:分讨,然后得二分左右端点,最后贪心
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
struct Car
{
int l,r;
int d,v,a;
bool st;
}c[N];
int n,m,L,v;
int pos[N];
int binary(int d) //behind
{
int l=1,r=m,mid;
while(l<r)
{
mid=(l+r)>>1;
if(pos[mid]>=d) r=mid;
else l=mid+1;
}
if(pos[l]<d) return -1;
return l;
}
int binary2(int d) //front
{
int l=1,r=m,mid;
while(l<r)
{
mid=(l+r+1)>>1;
if(pos[mid]<=d) l=mid;
else r=mid-1;
}
if(pos[l]>d) return -1;
return l;
}
bool calc(Car &car)
{
if(car.a==0)
{
if(car.v<=v) return 0;
int bi=binary(car.d);
if(bi==-1) return 0;
car.st=1,car.l=bi,car.r=m;
}
else if(car.a>0)
{
if(car.v>v)
{
int bi=binary(car.d);
if(bi==-1) return 0;
car.st=1,car.l=bi,car.r=m;
}
else
{
double temp=(v*v-car.v*car.v)*1.0/(2*car.a)+car.d;
if(temp>L) return 0;
int bi=binary((int)temp+1);
if(bi==-1) return 0;
car.st=1,car.l=bi,car.r=m;
}
}
else if(car.a<0)
{
if(car.v<=v) return 0;
int bi1=binary(car.d);
if(bi1==-1) return 0;
double temp=(v*v-car.v*car.v)*1.0/(2*car.a)+car.d;
if(pos[bi1]>=temp) return 0;
int bi2;
if((v*v-car.v*car.v)%(2*car.a)==0) bi2=binary2((int)temp-1);
else bi2=binary2((int)temp);
car.st=1,car.l=bi1,car.r=bi2;
}
return 1;
}
bool cmp(Car x,Car y)
{
return x.r<y.r;
}
signed main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--)
{
int ans1=0,ans2=0;
cin>>n>>m>>L>>v;
for(int i=1; i<=n; i++) cin>>c[i].d>>c[i].v>>c[i].a;
for(int i=1; i<=m; i++) cin>>pos[i];
for(int i=1; i<=n; i++) if(calc(c[i])) ans1++;
int lst=-1;
sort(c+1,c+1+n,cmp);
for(int i=1; i<=n; i++)
{
if(!c[i].st) continue;
if(c[i].l<=lst) continue;
lst=c[i].r,ans2++;
}
cout<<ans1<<" "<<m-ans2<<"\n";
}
return 0;
}