题意:有R G B三种颜色的矩形并在一起,两两颜色和三种颜色一起可以搞出另外4中颜色,问最终所有7种面积和为多少。
题解:y轴离散化,x轴扫描,线段树区间维护7种颜色的有效长度。具体来说:首先不考虑区间的lazy,求出区间7种颜色有效长度,然后考虑lazy,
拿区间 R lazy举例,R 可以把无色染成R ,G染成RG,B染成RB,GB染成RGB,B G lazy做做相同转化即可。
Sure原创,转载请注明出处。
#include <iostream> #include <cstdio> #include <memory.h> #include <algorithm> using namespace std; const int maxn = 10002; struct line { int x,down,up; int left; bool operator < (const line &other) const { if(x == other.x) return left > other.left; return x < other.x; } }vertical_line[maxn << 1]; struct node { int l,r; __int64 len[8]; int lazy[4]; }seg[maxn << 3]; int yy[maxn << 1]; __int64 area[8]; int n,top,tot; inline int ABS(int x) { return x >= 0 ? (x) : (-x); } void addmatrix(char c,int x1,int y1,int x2,int y2) { int t; if(c == 'R') t = 1; else if(c == 'G') t = 2; else t = 3; vertical_line[tot].x = x1; vertical_line[tot].down = y1; vertical_line[tot].up = y2; vertical_line[tot].left = t; tot++; vertical_line[tot].x = x2; vertical_line[tot].down = y1; vertical_line[tot].up = y2; vertical_line[tot].left = -t; tot++; return; } void read() { top = tot = 0; char str[3]; int x1,x2,y1,y2; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%s %d %d %d %d ",str,&x1,&y1,&x2,&y2); yy[top++] = y1; yy[top++] = y2; addmatrix(str[0],x1,y1,x2,y2); } sort(vertical_line , vertical_line + tot); sort(yy , yy + top); top = unique(yy , yy + top) - yy; return; } void biuld(int l,int r,int num) { seg[num].l = l; seg[num].r = r; seg[num].len[0] = 1LL * (yy[r] - yy[l]); for(int i=1;i<=7;i++) { if(i <= 3) seg[num].lazy[i] = 0; seg[num].len[i] = 0LL; } if(l + 1 == r) return; int mid = (l + r) >> 1; biuld(l , mid , num << 1); biuld(mid , r , num << 1 | 1); return; } void UP(int num) { __int64 sum = 0; for(int i=0;i<=7;i++) { if(seg[num].l + 1 == seg[num].r) { seg[num].len[i] = 0LL; } else { seg[num].len[i] = seg[num << 1].len[i] + seg[num << 1 | 1].len[i]; } if(i) sum += seg[num].len[i]; } seg[num].len[0] = 1LL * (yy[seg[num].r] - yy[seg[num].l]) - sum; int tmp; if(seg[num].lazy[1] > 0) { tmp = seg[num].len[0]; seg[num].len[0] = 0; seg[num].len[1] += tmp; tmp = seg[num].len[2]; seg[num].len[2] = 0; seg[num].len[4] += tmp; tmp = seg[num].len[3]; seg[num].len[3] = 0; seg[num].len[5] += tmp; tmp = seg[num].len[6]; seg[num].len[6] = 0; seg[num].len[7] += tmp; } if(seg[num].lazy[2] > 0) { tmp = seg[num].len[0]; seg[num].len[0] = 0; seg[num].len[2] += tmp; tmp = seg[num].len[1]; seg[num].len[1] = 0; seg[num].len[4] += tmp; tmp = seg[num].len[3]; seg[num].len[3] = 0; seg[num].len[6] += tmp; tmp = seg[num].len[5]; seg[num].len[5] = 0; seg[num].len[7] += tmp; } if(seg[num].lazy[3] > 0) { tmp = seg[num].len[0]; seg[num].len[0] = 0; seg[num].len[3] += tmp; tmp = seg[num].len[1]; seg[num].len[1] = 0; seg[num].len[5] += tmp; tmp = seg[num].len[2]; seg[num].len[2] = 0; seg[num].len[6] += tmp; tmp = seg[num].len[4]; seg[num].len[4] = 0; seg[num].len[7] += tmp; } return; } void update(int l,int r,int num,int val) { if(l == seg[num].l && r == seg[num].r) { seg[num].lazy[ABS(val)] += val; UP(num); return; } int mid = (seg[num].l + seg[num].r) >> 1; if(mid >= r) update(l , r , num << 1 , val); else if(l >= mid) update(l , r , num << 1 | 1 , val); else { update(l , mid , num << 1 , val); update(mid , r , num << 1 | 1 , val); } UP(num); return; } void addline(int i) { int bjd = lower_bound(yy , yy + top , vertical_line[i].down) - yy; int bju = lower_bound(yy , yy + top , vertical_line[i].up) - yy; if(bjd != bju) update(bjd , bju , 1 , vertical_line[i].left); return; } void solve() { memset(area,0,sizeof(area)); addline(0); for(int i=1;i<tot;i++) { for(int j=1;j<=7;j++) { area[j] += seg[1].len[j] * (vertical_line[i].x - vertical_line[i-1].x); } addline(i); } for(int i=1;i<=7;i++) { printf("%I64d\n",area[i]); } return; } int main() { int cas; scanf("%d",&cas); for(int i=1;i<=cas;i++) { printf("Case %d:\n",i); read(); biuld(0,top-1,1); solve(); } return 0; }