翻了题解区都发现没有我的做法。
大概就是说我当时想第二问可以贪心地去做,枚举监控,考虑是否有一辆车只经过这一个监控,如果有就不删,否则贪心删除。
通过大样例+对拍+官方数据,但是不会证明/wul
类似的考场代码:
#include <bits/stdc++.h>
#define ll long long
#define N 1000010
using namespace std;
ll T, n, m, L, V;
struct car {
ll d, v, a, l, r;
} a[N];
ll t[N], p[N];
void upd(ll x, ll v) {
x ++;
for(; x <= L + 2; x += x & -x) t[x] += v;
}
ll qry(ll x) {
x ++;
ll res = 0;
for(; x > 0; x -= x & -x) res += t[x];
return res;
}
void solve() {
scanf("%lld %lld %lld %lld", &n, &m, &L, &V);
for(ll i = 1; i <= n; i ++) {
scanf("%lld %lld %lld", &a[i].d, &a[i].v, &a[i].a);
if(a[i].a > 0) {
if(a[i].v * a[i].v + 2 * a[i].a * (L - a[i].d) > V * V) {
a[i].r = L;
ll l = a[i].d, r = L;
while(l <= r) {
ll mid = (l + r) >> 1;
if(a[i].v * a[i].v + 2 * a[i].a * (mid - a[i].d) > V * V) {
a[i].l = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
} else {
a[i].l = a[i].r = L + 1;
}
} else if(a[i].a == 0) {
if(a[i].v > V) {
a[i].l = a[i].d;
a[i].r = L;
} else {
a[i].l = a[i].r = L + 1;
}
} else {
if(a[i].v > V) {
a[i].l = a[i].d;
ll l = a[i].d, r = L;
while(l <= r) {
ll mid = (l + r) >> 1;
if(a[i].v * a[i].v + 2 * a[i].a * (mid - a[i].d) > V * V) {
a[i].r = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
} else {
a[i].l = a[i].r = L + 1;
}
}
}
ll ans1 = 0, ans2 = 0;
for(ll i = 1; i <= L + 2; i ++) t[i] = 0;
for(ll i = 1; i <= m; i ++) {
scanf("%lld", &p[i]);
upd(p[i], 1);
}
for(ll i = 1; i <= n; i ++) {
if(qry(a[i].r) - qry(a[i].l - 1)) {
ans1 ++;
}
}
sort(a + 1, a + n + 1, [](car a, car b) {
return a.l < b.l;
});
for(ll i = 1; i <= L + 2; i ++) t[i] = 0;
ll pos1 = 1, pos2 = 1;
p[m + 1] = L + 1;
for(ll i = 1; i <= m; i ++) {
while(pos1 <= n && a[pos1].l <= p[i]) {
upd(a[pos1].r, 1);
pos1 ++;
}
if(qry(p[i + 1] - 1) - qry(p[i] - 1)) {
while(pos2 <= n && a[pos2].l <= p[i]) {
upd(a[pos2].r, -1);
pos2 ++;
}
} else {
ans2 ++;
}
}
printf("%lld %lld\n", ans1, ans2);
}
int main() {
scanf("%lld", &T);
while(T --) {
solve();
}
}