之前写过一次,这次是在学习扫描线,顺道想起来这个题目了,那就用扫描线再写一遍吧
扫描线的思想很简单,去网上找几个blog看一下就会了,不多赘述
吐槽一句:评测机毛病真多,我调用个sort明明加了using namespace std; 还提示我需要在sort前面加std,pragma指令也不能用,会报编译错误,自定义排序 boo cmp()的参数写成 p& a就编译错误,必须去掉&符号,之前没那么多毛病啊,难道评测机感冒了?下面这个代码还是上述问题,如果要提交的话请自行删改相应内容。
这个是O()的时间复杂度,可以用线段树优化到O(
)
#include <bits/stdc++.h>
#pragma warning (disable:4996)
#define mem(a, b) memset(a, b, sizeof a)
#pragma warning (disable:6031)
typedef long long ll;
using namespace std;
const int N = 310;
struct p {
ll x, y1, y2, mark;
p() {}
p(ll x, ll y1, ll y2, ll mark) {this->x = x;this->y1 = y1;this->y2 = y2;this->mark = mark;}
}arr[N];
bool cmp(p& a, p& b) {
return a.x < b.x;
}
ll dy[N];
ll c[N];// 记录区间出现次数
ll get(ll y) {
return std::lower_bound(dy + 1, dy + 5, y) - (dy);
}
int main()
{
ll t;
scanf("%lld", &t);
while (t--) {
ll x1, x2, y1, y2;
scanf("%lld %lld %lld %lld", &x1, &y2, &x2, &y1);
arr[1] = p(x1, y1, y2, 1);
arr[2] = p(x2, y1, y2, -1);
ll x3, y3, x4, y4;
scanf("%lld %lld %lld %lld", &x3, &y4, &x4, &y3);
arr[3] = p(x3, y3, y4, 1);
arr[4] = p(x4, y3, y4, -1);
std::sort(arr + 1, arr + 5, cmp);
dy[1] = y1;
dy[2] = y2;
dy[3] = y3;
dy[4] = y4;
std::sort(dy + 1, dy + 5);
ll len = unique(dy + 1, dy + 5) - (dy + 1);// 离散化后的实际长度
ll last = arr[1].x;
mem(c, 0);
ll res = 0;
for (ll i = get(arr[1].y1); i < get(arr[1].y2); i++) {
c[i] += arr[1].mark;
}
for (ll i = 2; i <= 4; i++) {
ll now = arr[i].x;
ll ans = 0;
for (ll j = 1; j <= len; j++) {
if (c[j]) {
ans += dy[j + 1] - dy[j];
}
}
res += (now - last) * ans;
last = now;
for (ll j = get(arr[i].y1); j < get(arr[i].y2); j++) {
c[j] += arr[i].mark;
}
}
printf("%lld\n", res);
}
return 0;
}