扫描线-二维数点:
离散化,离线向上扫描y轴,树状数组维护当前存在多少点(x, y)的 y <= qy。
区间点数为:+ <=x2<=y2 + <=x1 - 1<=y1 - 1 - <=x1 - 1<=y2 - <=x2<=y1 - 1.
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define PII pair<int, int>
#define endl "\n"
const int MAX = 1e9;
const int N = 200010;
vector<int> vx;
vector<array<int, 4>> event;
int n, q, m;
int c[N];
int query(int x)
{
int s = 0;
for (; x; x -= x & (-x))
{
s += c[x];
}
return s;
}
void modify(int x, int s)
{
for (; x <= m; x += x & (-x))
{
c[x] += s;
}
}
// (i, a[i])
int main()
{
cin >> n >> q;
vector<int> ans(q + 1);
for (int i = 1; i <= n; i++)
{
int x, y;
cin >> x >> y;
vx.push_back(x);
event.push_back({y, 0, x});
}
for (int i = 1; i <= q; i++)
{
int x1, x2, y1, y2;
cin >> x1 >> x2 >> y1 >> y2;
event.push_back({y2, 2, x2, i});
event.push_back({y1 - 1, 2, x1 - 1, i});
event.push_back({y2, 1, x1 - 1, i});
event.push_back({y1 - 1, 1, x2, i});
}
sort(event.begin(), event.end());
sort(vx.begin(), vx.end());
vx.erase(unique(vx.begin(), vx.end()), vx.end());
m = vx.size();
for (auto evt : event)
{
if (evt[1] == 0)
{
int y = lower_bound(vx.begin(), vx.end(), evt[2]) - vx.begin() + 1;
modify(y, 1);
}
else
{
int y = upper_bound(vx.begin(), vx.end(), evt[2]) - vx.begin();
int tmp = query(y);
if (evt[1] == 1)
ans[evt[3]] -= tmp;
else
ans[evt[3]] += tmp;
}
}
for (int i = 1; i <= q; i++)
{
cout << ans[i] << ' ';
}
cout << endl;
}
扫描线--矩形面积并问题
线段树储存最小值及出现个数维护当前 y 周未被覆盖长度。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define PII pair<int, int>
#define endl "\n"
const int MAX = 1e9;
const int N = 200010;
vector<int> vx;
vector<array<int, 4>> event;
int n, m, ans;
struct info
{
int minv, mincnt;
};
info operator+(const info &l, const info &r)
{
info a;
a.minv = min(l.minv, r.minv);
if (l.minv == r.minv)
a.mincnt = l.mincnt + r.mincnt;
else if (l.minv < r.minv)
a.mincnt = l.mincnt;
else
a.mincnt = r.mincnt;
return a;
}
struct node
{
int t;
info val;
} seg[N * 8];
void updata(int id)
{
seg[id].val = seg[id * 2].val + seg[id * 2 + 1].val;
}
void settag(int id, int t)
{
seg[id].val.minv = seg[id].val.minv + t;
seg[id].t += t;
}
void pushdown(int id)
{
if (seg[id].t != 0)
{
settag(id * 2, seg[id].t);
settag(id * 2 + 1, seg[id].t);
seg[id].t = 0;
}
}
void build(int id, int l, int r)
{
if (l == r)
{
seg[id].val = {0, vx[r] - vx[r - 1]};
return;
}
int mid = (l + r) / 2;
build(id * 2, l, mid);
build(id * 2 + 1, mid + 1, r);
updata(id);
}
void modify(int id, int l, int r, int ql, int qr, int t)
{
if (ql == l && qr == r)
{
settag(id, t);
return;
}
int mid = (l + r) / 2;
pushdown(id);
if (qr <= mid)
modify(id * 2, l, mid, ql, qr, t);
else if (ql > mid)
modify(id * 2 + 1, mid + 1, r, ql, qr, t);
else
{
modify(id * 2, l, mid, ql, mid, t);
modify(id * 2 + 1, mid + 1, r, mid + 1, qr, t);
}
updata(id);
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
int x1, x2, y1, y2;
cin >> x1 >> x2 >> y1 >> y2;
vx.push_back(x1);
vx.push_back(x2);
event.push_back({y1, 1, x1, x2});
event.push_back({y2, -1, x1, x2});
}
sort(event.begin(), event.end());
sort(vx.begin(), vx.end());
vx.erase(unique(vx.begin(), vx.end()), vx.end());
m = vx.size() - 1;
build(1, 1, m);
int prey = 0;
int totlen = seg[1].val.mincnt;
for (auto evt : event)
{
int cov = totlen;
if (seg[1].val.minv == 0)
cov = totlen - seg[1].val.mincnt;
ans += (evt[0] - prey) * cov;
prey = evt[0];
int x1 = lower_bound(vx.begin(), vx.end(), evt[2]) - vx.begin() + 1;
int x2 = lower_bound(vx.begin(), vx.end(), evt[3]) - vx.begin();
if (x1 > x2)
continue;
modify(1, 1, m, x1, x2, evt[1]);
}
cout << ans << endl;
}