二分+贪心,只能过样例1和2,样例3区间选点选出来错误,样例4和5没一个数据是对的。从早上八点干到十一点半,中途只休息了10分钟。
非常好题目,使我的100+行代码旋转。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,m,L,v;
struct node{
int d,v0,a;
}arr[N];
struct lrnode{
int l,r;
}dp[N];
int drr[N];
bool cmp1(lrnode a,lrnode b){return a.r<b.r;}
int upbs(int i,int b){//加速在哪里大于v (或无解)
int l=b,r=m,res=-1;
while(l<=r){
int mid=(l+r)>>1;
if((drr[mid]-arr[i].d)*2*arr[i].a+arr[i].v0*arr[i].v0>v*v){
r=mid-1;
res=mid;
}else l=mid+1;
}
return res;
}
int downbs(int i,int b){//减速在哪里最后大于v?
int l=b,r=m,res=-1;
while(l<=r){
int mid=(l+r)>>1;
if((drr[mid]-arr[i].d)*2*arr[i].a+arr[i].v0*arr[i].v0>v*v){
l=mid+1;
res=mid;
}else r=mid-1;
}
return res;
}
void sovled(){
int ans=0,ans2=0;
memset(arr,0,sizeof(arr));
memset(dp,0,sizeof(dp));
memset(drr,0,sizeof(drr));
scanf("%d%d%d%d",&n,&m,&L,&v);
for(int i=1;i<=n;i++) scanf("%d%d%d",&arr[i].d,&arr[i].v0,&arr[i].a);
for(int i=1;i<=m;i++) scanf("%d",&drr[i]);
sort(drr+1,drr+m+1);
for(int i=1;i<=n;i++){
int v0=arr[i].v0,d=arr[i].d;
if(d>drr[m]){
dp[i].l=dp[i].r=-1;
continue;
}
int b=lower_bound(drr+1,drr+n+1,d)-drr;
// cout<<b<<",\n";
if(arr[i].a>0){
if(v0>v) dp[i].l=b,dp[i].r=m,ans++;
else{
int c=upbs(i,b);
if(c==-1) dp[i].l=dp[i].r=-1;
else{
dp[i].l=c,dp[i].r=m;
ans++;
}
}
}else if(arr[i].a==0){
if(v0>v) dp[i].l=b,dp[i].r=m,ans++;
else dp[i].l=dp[i].r=-1;
}else{
if(v0>v){
int c=downbs(i,b);
if(c==-1) dp[i].l=dp[i].r=-1;
else{//
dp[i].l=b,dp[i].r=c;
ans++;
}
}else dp[i].l=dp[i].r=-1;
}
// printf("%d %d\n",dp[i].l,dp[i].r);
}
printf("%d ",ans);
if(ans==0){
printf("%d\n",m);
return ;
}
sort(dp+1,dp+n+1,cmp1);
int rnow=1;
for(;rnow<=n;rnow++){
if(dp[rnow].r!=-1){
break;
}
}
if(rnow<=n) ans2++;
for(int i=rnow+1;i<=n;i++){
if(dp[i].l>dp[rnow].r){
rnow=i;
ans2++;
}
}
printf("%d\n",m-ans2);
return ;
}
int main(){
//freopen("detect3.in","r",stdin);
//freopen("detect3.out","w",stdout);
int t;
scanf("%d",&t);
while(t--){
sovled();
}
return 0;
}
/*
**超过**道路限速 V 完啦! =(
*/