题目链接:点击打开链接
题意:给定由红绿蓝组成的一些矩阵
输出每种颜色对应的面积。
思路:
如果颜色只有一种就是扫描线。
这里先求出包含各类颜色的面积,然后容斥一下得到答案。
画个图就能快速得到答案了
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std; template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x <0) {
putchar('-');
x = -x;
}
if (x>9) pt(x / 10);
putchar(x % 10 + '0');
}
#define N 200005
#define L(x) (x<<1)
#define R(x) (x<<1|1)
typedef long long ll;
ll Mid(ll a, ll b){ return (a + b) >> 1; }
//这份代码是对y轴建树,从左到右扫
struct node{ //这个区间被c条线段覆盖了
ll l, r;
ll c; //用来记录重叠情况
ll cnt, lf, rf;//离散点l对应的实际点lf cnt表示这个区间内存在的线段长度
}tree[N * 4];
struct Line{
ll x, y1, y2;
ll f, col;
Line(ll a = 0.0, ll b = 0.0, ll c = 0.0, ll d = 0, ll e = 0) :x(a), y1(b), y2(c), f(d), col(e){}
}line[N * 2];
bool cmp(Line a, Line b){ return a.x<b.x; }
ll y[N];
void build(ll l, ll r, ll id){
tree[id].l = l, tree[id].r = r;
tree[id].cnt = tree[id].c = 0;
tree[id].lf = y[l]; tree[id].rf = y[r];
if (l + 1 == r)return;
ll mid = Mid(l, r);
build(l, mid, L(id));
build(mid, r, R(id));
}
void push_up(ll id){
if (tree[id].c){
tree[id].cnt = tree[id].rf - tree[id].lf;
return;
}
if (tree[id].l + 1 == tree[id].r) tree[id].cnt = 0;
else tree[id].cnt = tree[L(id)].cnt + tree[R(id)].cnt;
}
void update(ll id, Line e){
if (e.y1 == tree[id].lf && tree[id].rf == e.y2){
tree[id].c += e.f;
push_up(id); return;
}
if (e.y2 <= tree[L(id)].rf)
update(L(id), e);
else if (tree[R(id)].lf <= e.y1)
update(R(id), e);
else {
Line tmp = e; tmp.y2 = tree[L(id)].rf; update(L(id), tmp);
tmp = e; tmp.y1 = tree[R(id)].lf; update(R(id), tmp);
}
push_up(id);
}
set<ll>myset;
set<ll>::iterator p;
ll siz, top;
ll ALL(int x1, int x2 = -1, int x3 = -1){
build(1, siz - 1, 1);
int i = 1, last;
for (; i < top;i++)
if (line[i].col == x1 || line[i].col == x2 || line[i].col == x3){
update(1, line[i]);
last = i;
i++; break;
}
ll all = 0;
for (; i < top; i++)
if (line[i].col == x1 || line[i].col == x2 || line[i].col == x3){
all += tree[1].cnt * (line[i].x - line[last].x);
update(1, line[i]);
last = i;
}
return all;
}
int main(){
ll i, j, n;
int T, Cas = 1; rd(T);
ll x1, x2, y1, y2;
while (T--){
rd(n); myset.clear(); top = 1;
for (i = 1; i <= n; i++){
char str[2]; scanf("%s", str); int col = 0; if (str[0] == 'G')col = 1; else if (str[0] == 'B')col = 2;
rd(x1); rd(y1); rd(x2); rd(y2);
if (x1 > x2)swap(x1, x2); if (y1 > y2)swap(y1, y2);
myset.insert(y1); myset.insert(y2);
Line E = Line(x1, y1, y2, 1, col);
line[top++] = E;
Line E2 = Line(x2, y1, y2, -1, col);
line[top++] = E2;
}
sort(line + 1, line + top, cmp);
siz = 1; for (p = myset.begin(); p != myset.end(); p++) y[siz++] = *p;
ll all = ALL(0,1,2);
ll RG = ALL(0, 1), RB = ALL(0, 2), GB = ALL(1, 2);
ll R = ALL(0), G = ALL(1), B = ALL(2);
printf("Case %d:\n", Cas++);
ll r = all - GB, g = all - RB, b = all - RG;
ll tmp = all - r - g - b;
ll gb = tmp - (R - r);
ll rb = tmp - (G - g);
ll rg = tmp - (B - b);
ll rgb = tmp - rg - rb - gb;
pt(r); puts("");
pt(g); puts("");
pt(b); puts("");
pt(rg); puts("");
pt(rb); puts("");
pt(gb); puts("");
pt(rgb); puts("");
}
return 0;
}