题意:有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;
}