题意:给出红绿蓝三种颜色的矩形,某些元素重叠之后会组合成其它颜色,问7种颜色的面积分别为多少。
解法:考虑只有两种颜色AB,那么求A颜色矩形的面积并x,B颜色矩形的面积并为y,AB颜色矩形的面积并为z,则最终,AB颜色的面积为x+y-z,A颜色的面积为x-(x+y-z),B颜色的面积为y-(x+y-z);
类似得,考虑三种颜色:
根据公式先求出三种颜色混和的面积x,然后依次只考虑两种只有两种颜色,求出RG,RB,GB后减去x,分别得到两种颜色混合的面积,然后再求出只有一种颜色的面积。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<map> using namespace std; const int maxn = 20010; int hash[maxn]; struct node { int left, right, key; long long sum; void init(int l, int r) { left = l; right = r; key=0; sum=0; } int mid() { return (left + right) >> 1; } int length() { return hash[right+1] - hash[left]; } }; struct SegTree { node tree[maxn * 4]; void init(int l, int r, int idx) { tree[idx].init(l, r); if (l == r) return; int mid = tree[idx].mid(); init(l, mid, idx << 1); init(mid + 1, r, (idx << 1) | 1); } void pushup(int idx) { if (tree[idx].key > 0) tree[idx].sum=tree[idx].length(); else { if (tree[idx].left == tree[idx].right) tree[idx].sum = 0; else tree[idx].sum = tree[idx << 1].sum + tree[(idx << 1) | 1].sum; } } void update(int left, int right, int idx, int v) { if (tree[idx].left >= left && tree[idx].right <= right) { tree[idx].key += v; pushup(idx); return; } int mid = tree[idx].mid(); if (left <= mid) update(left, right, idx << 1, v); if (right > mid) update(left, right, (idx << 1) | 1, v); pushup(idx); } }; struct edge { int type, color; int s, t, x; void init(int c, int x, int s, int t, int type) { color = c; this->x = x; this->s = s; this->t = t; this->type = type; } bool operator <(const edge oth) const { return x < oth.x || (x == oth.x && type > oth.type); } }; SegTree st; edge ed[maxn]; map<int, int> mp; int n, cnt; void init() { mp.clear(); int a, b, c, d, k; char ch[10]; scanf("%d",&n); for (int i = 1; i <= n; i++) { scanf("%s%d%d%d%d", ch, &a, &b, &c, &d); if (ch[0] == 'R') k = 0; else if (ch[0] == 'G') k = 1; else k = 2; ed[i].init(k, a, b, d, 1); ed[n + i].init(k, c, b, d, -1); mp[b] = 0; mp[d] = 0; } sort(ed + 1, ed + n * 2 + 1); cnt = 0; for (map<int, int>::iterator it = mp.begin(); it != mp.end(); it++){ (*it).second = ++cnt; hash[cnt]=(*it).first; } } bool flag[3]; void set(int a, int b, int c) { flag[0] = a; flag[1] = b; flag[2] = c; } long long get() { long long ans = 0; st.init(1, cnt - 1, 1); int i = 1; while (i<=2*n&&!flag[ed[i].color]) i++; if(i>2*n) return 0; st.update(mp[ed[i].s], mp[ed[i].t] - 1, 1, ed[i].type); int pre=ed[i].x; i++; for (; i <= n * 2; i++) { if (!flag[ed[i].color]) continue; ans += st.tree[1].sum * (ed[i].x - pre); pre=ed[i].x; st.update(mp[ed[i].s], mp[ed[i].t] - 1, 1, ed[i].type); } return ans; } long long ans[10];//R G B RG RB GB RGB void work() { set(1, 0, 0); ans[1] = get();//R set(0, 1, 0); ans[2] = get();//G set(0, 0, 1); ans[3] = get();//B set(1, 1, 1); long long all = get(); set(1, 1, 0); long long ab = ans[1] + ans[2] - get(); set(1, 0, 1); long long ac = ans[1] + ans[3] - get(); set(0, 1, 1); long long bc = ans[3] + ans[2] - get(); ans[7]=all-ans[1]-ans[2]-ans[3]+ab+ac+bc; ans[4]=ab-ans[7]; ans[5]=ac-ans[7]; ans[6]=bc-ans[7]; ans[1]=ans[1]-ans[4]-ans[5]-ans[7]; ans[2]=ans[2]-ans[4]-ans[6]-ans[7]; ans[3]=ans[3]-ans[5]-ans[6]-ans[7]; } int main() { int cas; scanf("%d",&cas); for(int c=1;c<=cas;c++){ init(); work(); printf("Case %d:\n",c); for(int i=1;i<=7;i++) printf("%I64d\n",ans[i]); } return 0; }