rt 马蜂较为良好
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x = 0, f = 1; char c = getchar();
while(c > '9' || c < '0') {if(c == '-') f = -1; c = getchar();}
while(c <= '9' && c >= '0') {x = x * 10 + c - '0'; c = getchar();}
return x * f;
}
const int maxn = 1e5 + 10;
const int N = 1e6 + 10;
struct Node
{
int l, r;
int maxa;
int sum;
#define lson (id<<1)
#define rson (id<<1|1)
}t[N<<2];
struct node
{
int l, r;
int flag;
int d, v, a;
}q[maxn];
int n, m, L, V;
int T;
int det[N];
int ans1, ans2;
bool cmp(node a, node b) {return a.r < b.r;}
void update(int id)
{
t[id].maxa = max(t[lson].maxa, t[rson].maxa);
t[id].sum = max(t[lson].sum, t[rson].sum);
}
void build(int id, int L, int R)
{
t[id].l = L; t[id].r = R;
if(L == R)
{
if(!det[L]) t[id].maxa = 0;
else t[id].maxa = L;
t[id].sum = 0;
return;
}
int mid = L + R >> 1;
build(lson, L, mid);
build(rson, mid+1, R);
update(id);
}
void printtree(int id)
{
printf("id:%d, l:%d, r:%d, maxa:%d, sum:%d\n", id, t[id].l, t[id].r, t[id].maxa, t[id].sum);
if(t[id].l == t[id].r) return;
printtree(lson);
printtree(rson);
}
void change(int id, int L, int R)
{
if(t[id].l == t[id].r)
{
t[id].sum = 1;
return;
}
int mid = t[id].l + t[id].r >> 1;
if(L <= mid) change(lson, L, R);
if(R > mid) change(rson, L, R);
update(id);
}
int query(int id, int L, int R)
{
if(t[id].l >= L && t[id].r <= R) return t[id].sum;
int mid = t[id].l + t[id].r >> 1, ans = 0;
if(L <= mid) ans = max(ans, query(lson, L, R));
if(R > mid) ans = max(ans, query(rson, L, R));
return ans;
}
int find(int id, int L, int R)
{
if(t[id].l >= L && t[id].r <= R) return t[id].maxa;
int mid = t[id].l + t[id].r >> 1, ans = 0;
if(L <= mid) ans = max(ans, find(lson, L, R));
if(R > mid) ans = max(ans, find(rson, L, R));
return ans;
}
int main()
{
// freopen("detect4.in", "r", stdin);
// freopen("detect.out", "w", stdout);
T = read();
while(T--)
{
ans1 = ans2 = 0;
memset(q, 0, sizeof(q));
n = read(), m = read(), L = read(), V = read();
for(int i = 1; i <= L+1; i++) det[i] = 0;
for(int i = 1; i <= n; i++)
{
q[i].d = read(), q[i].v = read(), q[i].a = read();
if(q[i].v > V)
{
q[i].flag = 1;
q[i].l = q[i].d+1;
if(q[i].a >= 0) q[i].r = L+1;
else
{
double dis = (double)((V * V) - (q[i].v * q[i].v)) / (double)(2 * q[i].a);
if(dis != floor(dis)) q[i].r = q[i].d + (int)floor(dis) + 1;
else q[i].r = q[i].d + (int)dis;
}
}
else if(q[i].v == V)
{
if(q[i].a > 0)
{
if(q[i].d == L) continue;
q[i].flag = 1;
q[i].l = q[i].d+2;
q[i].r = L+1;
}
}
else
{
if(q[i].a > 0)
{
double dis = (double)((V * V) - (q[i].v * q[i].v)) - (double)(2 * q[i].a);
if((double)q[i].d+dis+1 <= (double)L+1)
{
q[i].flag = 1;
if(dis != ceil(dis)) q[i].l = q[i].d+(int)ceil(dis)+1;
else q[i].l = q[i].d+(int)dis+2;
q[i].r = L+1;
}
}
}
}
for(int i = 1; i <= m; i++) {int x = read(); det[x+1] = 1;}
build(1, 1, L+1);
// printtree(1);
sort(q+1, q+n+1, cmp);
// for(int i = 1; i <= n; i++)
// {
// cout << q[i].id << ":";
// cout << q[i].l << " " << q[i].r << " " << q[i].flag << endl;
// }
for(int i = 1; i <= n; i++)
{
if(!q[i].flag) continue;
int l = q[i].l, r = q[i].r;
int pos = find(1, l, r);
if(pos)
{
ans1++;
if(!query(1, l, r)) {ans2++; change(1, pos, pos);}
}
}
cout << ans1 << " " << m-ans2 << endl;
}
return 0;
}