题目链接
思路
只需要考虑点落在矩形内的时间段内,于是可以将时间看做坐标轴,求点落在矩形内的区间,然后想象一个时间t从左到右扫描,使得与最多区间相交
并且将遇到左端点和右端点分别看做事件,扫描的过程就是处理事件的过程
细节
- 因为点落在矩形边上不算,因此区间应该为开区间
- 区间1和区间2的左右端点重合时应先处理右端点事件,再处理左端点事件
代码
开始一直WA是因为a == 0的时候,一直写的!a,还有a为负数的情况
#include <iostream>
#include <cstring>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <deque>
#include <bitset>
#include <algorithm>
using namespace std;
#define PI acos(-1.0)
#define LL long long
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define mp make_pair
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "wb", stdout)
#define scan(x) scanf("%d", &x)
#define scan2(x, y) scanf("%d%d", &x, &y)
#define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)
#define sqr(x) (x) * (x)
#define pr(x) cout << #x << " = " << x << endl
#define lc o << 1
#define rc o << 1 | 1
#define pl() cout << endl
const int maxn = 100000 + 10;
struct Event {
double x;
int type;
bool operator < (const Event &a) const {
return x < a.x || (x == a.x && type > a.type);
}
} event[maxn * 2];
void update(int x, int a, int w, double &L, double &R) {
//!a is wrong because a might be negative
if (a == 0) {
if (x <= 0 || x >= w) R = L - 1;
} else {
if (a > 0) {
L = max(L, (double)-x / a);
R = min(R, (double)(w - x) / a);
} else {
L = max(L, (double)(w - x) / a);
R = min(R, (double)-x / a);
}
}
}
int main() {
int T;
scan(T);
while (T--) {
int w, h, n, x, y, a, b;
int cnt = 0;
scan2(w, h);
scan(n);
for (int i = 0; i < n; i++) {
scanf("%d %d %d %d", &x, &y, &a, &b);
double L = 0, R = 1e9;
update(x, a, w, L, R);
update(y, b, h, L, R);
if (R > L) {
event[cnt++] = (Event){L, 0};
event[cnt++] = (Event){R, 1};
}
}
sort(event, event + cnt);
int tot = 0, ans = 0;
for (int i = 0; i < cnt; i++) {
if (event[i].type == 0) ans = max(ans, ++tot);
else tot--;
}
printf("%d\n", ans);
}
return 0;
}