这道题是用以悼念Renat Mullakhanov(rem)的。
二维平面上有N (1⩽N⩽30,000) 个矩形,求被至少K个矩形覆盖的区域的面积 (1⩽K⩽10) 。
用扫描线处理一维,另一维离散化之后建立线段树。
(不要随便看代码。不要随便看代码。不要随便看代码。重要的事情说三遍。 )
#include
#include
#include
#include
#include
#include
using namespace std;
//Global Variables & Definitions
#define MAXN 60060
#define MAXK 13
typedef long long LL;
int __T;
int N, K;
struct Point {
int X, Y;
Point() {}
Point(int X, int Y) : X(X), Y(Y) {}
inline void scan() {
scanf("%d%d", &X, &Y);
}
} P[MAXN * 2];
struct Line {
int X;
int Ya, Yb;
int V;
bool operator < (const Line & b) const {
return X < b.X;
}
void Set(int X, int Ya, int Yb, int V) {
this -> X = X;
this -> Ya = Ya;
this -> Yb = Yb;
this -> V = V;
}
} L[MAXN * 2];
map<int, int> V;
//End Global Variables & Definitions
//Segment Tree
int T;
int Y[MAXN * 2];
#define MAXT (MAXN << 2)
#define DEFINE_MID int mid = (l + r) >> 1
#define lson (u << 1)
#define rson (u << 1 | 1)
int leaf[MAXT];
int lazy[MAXT];
int sum[MAXT][MAXK];
void PushUp(int u) {
int l = u << 1, r = u << 1 | 1;
for(int i = 0;i < MAXK;++i) sum[u][i] = sum[l][i] + sum[r][i];
}
void Calc(int u) {
if(lazy[u] >= K) {
for(int i = 0;i < MAXK;++i) sum[u][i] = sum[u][0];
} else if(lazy[u]) {
int laz = lazy[u];
for(int i = 0;i <= laz;++i) sum[u][i] = sum[u][0];
if(leaf[u]) for(int i = laz + 1;i < MAXK;++i) sum[u][i] = 0;
else for(int i = laz + 1;i < MAXK;++i) sum[u][i] = sum[lson][i - laz] + sum[rson][i - laz];
} else {
if(leaf[u]) for(int i = 1;i < MAXK;++i) sum[u][i] = 0;
else PushUp(u);
}
}
void Build(int u, int l, int r) {
for(int i = 0;i < MAXK;++i) sum[u][i] = 0;
leaf[u] = lazy[u] = 0;
if(l == r) { sum[u][0] = Y[l] - Y[l - 1]; leaf[u] = 1; return; }
DEFINE_MID;
Build(lson, l, mid);
Build(rson, mid + 1, r);
PushUp(u);
}
inline int Query(int K) {
return sum[1][K];
}
void Update(int u, int l ,int r, int L, int R, int v) {
if(L <= l && R >= r) {
lazy[u] += v;
} else {
DEFINE_MID;
if(L <= mid) Update(lson, l, mid, L, R, v);
if(R > mid) Update(rson, mid + 1, r, L, R, v);
}
Calc(u);
}
//End Segment Tree
//Main Structure
inline void ir() {
scanf("%d%d", &N, &K);
int f, s;
for(int i = 0;i < N;++i) {
f = i << 1; s = f | 1;
P[f].scan();
P[s].scan();
//left close right open
++P[s].X;
++P[s].Y;
Y[f] = P[f].Y;
Y[s] = P[s].Y;
}
sort(Y, Y + N * 2);
T = unique(Y, Y + N * 2) - Y;
V.clear();
for(int i = 0;i < T;++i) V[Y[i]] = i;
Build(1, 1, T - 1);
/* */
for(int i = 0;i < N;++i) {
f = i << 1; s = f | 1;
L[f].Set(P[f].X, P[f].Y, P[s].Y, 1);
L[s].Set(P[s].X, P[f].Y, P[s].Y, -1);
}
sort(L, L + N * 2);
}
LL solve() {
ir();
int NN = N * 2;
LL res = 0ll;
for(int i = 0;i < NN;++i) {
if(i) res += (LL)(L[i].X - L[i - 1].X) * Query(K);
Update(1, 1, T - 1, V[L[i].Ya] + 1, V[L[i].Yb], L[i].V);
}
return res;
}
inline void g_ir() {
scanf("%d", &__T);
}
int main() {
g_ir();
int kase = 0;
while(__T--) printf("Case %d: %lld\n", ++kase, solve());
return 0;
}