前言
不评价 T1,三分钟切。
那就评价一下 T2,五分钟想到正解,十五分钟写完,由于二分原因调了四十五分钟,原地趋势。
题解
容易想到二分出每一辆车的超速区间,然后做区间选点贪心。
wt20 说可以直接平方后比大小就不用注意精度问题了。为什么我没想到。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 15;
const double P = 1e-7;
int T, n, m, L, V;
int d[N], v[N], a[N], p[N]; //初始位置、初始速度、加速度、测速仪位置
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (!(ch >= '0' && ch <= '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
struct node {
int l, r;
} seg[N]; int tot = 0;
bool cmp(node a, node b) {
if (a.r != b.r) return a.r < b.r;
return a.l < b.l;
}
int check(double a, double b) {
double x = fabs(a - b);
if (x > P) return a < b;
return 2; //a=b;
}
double get(double st, double ed, double beg, double add) {
double s = ed - st, tt = beg * beg + 2.0 * add * s;
if (tt < 0) return -1;
return sqrt(tt);
}
void init() {
tot = 0;
for (int i = 1; i <= n; i++) {
if (a[i] == 0) {
int pos = lower_bound(p + 1, p + 1 + m, d[i]) - p;
if (pos == m + 1) continue;
if (v[i] > V) seg[++tot] = (node){pos, m};
continue;
}
if (a[i] > 0) {
int pos = lower_bound(p + 1, p + 1 + m, d[i]) - p;
if (pos == m + 1) continue;
if (v[i] > V) {
seg[++tot] = (node){pos, m};
continue;
}
int l = pos, r = m + 1;
while (l < r) {
int mid = (l + r) >> 1;
if (check(get(d[i], p[mid], v[i], a[i]), V) >= 1) l = mid + 1; //v'<=V
else r = mid;
}
// while (pos <= m && check(get(d[i], p[pos], v[i], a[i]), V) >= 1) pos++; //<=
// if (pos == m + 1) continue;
// seg[++tot] = (node){pos, m};
if (l == m + 1) continue;
seg[++tot] = (node){l, m};
}
if (a[i] < 0) {
if (v[i] <= V) continue;
int pos = lower_bound(p + 1, p + 1 + m, d[i]) - p;
if (pos == m + 1) continue;
int l = pos - 1, r = m;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (check(get(d[i], p[mid], v[i], a[i]), V) == 0) l = mid;
else r = mid - 1;
}
if (l >= pos) seg[++tot] = (node){pos, l};
// int start = pos; pos--;
// while (pos < m && check(get(d[i], p[pos + 1], v[i], a[i]), V) == 0) pos++;
// if (pos >= start) {
//// cout << '\t' << i << ' ' << start << ' ' << pos << endl;
// seg[++tot] = (node){start, pos};
// }
}
}
// for (int i = 1; i <= n; i++, puts(""))
// for (int j = 1; j <= m; j++) {
// if (d[i] > p[j]) cout << "--";
// else cout << get(d[i], p[j], v[i], a[i]) << ' ';
// }
// for (int i = 1; i <= tot; i++) cout << seg[i].l << ' ' << seg[i].r << endl;
sort(seg + 1, seg + 1 + tot, cmp);
printf("%d ", tot); //ans1
}
int main() {
// freopen("detect.in", "r", stdin);
// freopen("detect.out", "w", stdout);
// scanf("%d", &T);
T = read();
while (T--) {
// scanf("%d%d%d%d", &n, &m, &L, &V);
n = read(), m = read(), L = read(), V = read();
for (int i = 1; i <= n; i++) d[i] = read(), v[i] = read(), a[i] = read();
for (int i = 1; i <= m; i++) p[i] = read();
// for (int i = 1; i <= n; i++) scanf("%d%d%d", &d[i], &v[i], &a[i]);
// for (int i = 1; i <= m; i++) scanf("%d", &p[i]);
init();
int R = 0, ans = 0;
for (int i = 1; i <= tot; i++)
if (R < seg[i].l) R = seg[i].r, ans++;
printf("%d\n", m - ans);
}
return 0;
}