题目连接:
http://acm.hdu.edu.cn/showproblem.php?pid=4419
第一次写博客,都点小小的激动,先废话一点。
题意:给你很多个矩形,分别用R G B表示每个矩形三种可能的颜色,重合的的部分为RG RB等颜色,求着七种颜色的面积分别是多少。
题解:最开始想到了用1 2 4分别表示这三种颜色,从而简化颜色的组合,但是始终没想到怎么去更新线段树,最后看了其他的大佬的东西才发现居然还有这种操作。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <cmath>
#define qq printf("QAQ\n");
#define ll long long
#define pf(num) printf("%lld\n",num);
using namespace std;
const int maxn=10005;
struct Edge{
int l,r,f,h;
}edge[maxn<<1];
int pos[maxn<<1];
int num,cnt;
struct tree{
int l,r,num[8],cover[8],cnt;
}t[maxn<<3];
bool cmp(Edge a,Edge b)
{
return a.h<b.h;
}
void build(int rt,int l,int r)
{
for(int i=1;i<8;i++)
t[rt].cover[i]=0,t[rt].num[i]=0;
t[rt].l=l,t[rt].r=r;
if(l==r)return ;
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void pushup(int rt)
{
int colour=1*(t[rt].num[1]>0)+2*(t[rt].num[2]>0)+4*(t[rt].num[4]>0);//是些什么颜色
//pf(colour);
for(int i=1;i<8;i++)
t[rt].cover[i]=0;
if(colour>0){
t[rt].cover[colour]=pos[t[rt].r+1]-pos[t[rt].l];
for(int i=1;i<8;i++)
if(colour!=colour|i){
int data=0;
if(t[rt].l!=t[rt].r)
data=t[rt<<1].cover[i]+t[rt<<1|1].cover[i];
t[rt].cover[colour|i]+=data;
t[rt].cover[colour]-=data;
}
}
else if(t[rt].l!=t[rt].r)//memset(t[rt].cover,0,sizeof t[rt].cover) ;
for(int i=1;i<8;i++)
t[rt].cover[i]=t[rt<<1].cover[i]+t[rt<<1|1].cover[i];
}
void updata(int rt,int l,int r,int data)
{
// if(l==r)
if(l<=t[rt].l&&t[rt].r<=r)
{
t[rt].num[abs(data)]+=data>0?1:-1;
pushup(rt);
return ;
}
int mid=(t[rt].l+t[rt].r)>>1;
if(mid>=r)updata(rt<<1,l,r,data);
else if(mid<l)updata(rt<<1|1,l,r,data);
else {
updata(rt<<1,l,mid,data);
updata(rt<<1|1,mid+1,r,data);
}
pushup(rt);
}
int find(int x)
{
int l=1,r=cnt;
while(l<=r)
{
int mid=(l+r)>>1;
if(pos[mid]==x)return mid;
if(x>pos[mid])l=mid+1;
else r=mid-1;
}
}
int main()
{
int tt,n;
scanf("%d",&tt);
for(int ttt=1;ttt<=tt;ttt++)
{
scanf("%d",&n);
num=n<<1;
int x1,y1,x2,y2;
char c;
for(int i=1;i<=n;i++)
{
cin>>c;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
edge[i].l=x1,edge[i].r=x2,edge[i].h=y1,edge[i].f=(c=='R'?1:(c=='G'?2:4)),pos[i]=x1;
edge[i+n].l=x1,edge[i+n].r=x2,edge[i+n].h=y2,edge[i+n].f=-(c=='R'?1:(c=='G'?2:4)),pos[i+n]=x2;//用1 2 4分别表示r g b 类比二进制
}
sort(pos+1,pos+num+1);
sort(edge+1,edge+num+1,cmp);
// for(int i=1;i<=num;i++)
// pf(edge[i].h);
cnt=2;
for(int i=2;i<=num;i++)
if(pos[i]!=pos[i-1])pos[cnt++]=pos[i];
cnt--;
build(1,1,cnt-1);
ll ans[8]={0};
for(int i=1;i<num;i++)
{
int l=find(edge[i].l);
int r=find(edge[i].r)-1;
updata(1,l,r,edge[i].f);
for(int j=1;j<8;j++)
ans[j]+=(ll)t[1].cover[j]*(edge[i+1].h-edge[i].h);
}
printf("Case %d:\n",ttt);
printf("%lld\n%lld\n%lld\n%lld\n%lld\n%lld\n%lld\n",ans[1],ans[2],ans[4],ans[3],ans[5],ans[6],ans[7]);
}
return 0;
}