您的位置:首页 > 理论基础 > 计算机网络

hdu 4419 2012杭州网络赛

2012-10-28 10:36 260 查看
题目大意:给出一些有颜色的矩形,会重叠,问最后每种颜色的面积为多少。。

当时网络赛不会做,最近学习了一下大神的做法,总算明白了。

我们可以将 三基色 RGB 以及其 衍生出来的其他颜色 化成 二进制表示 xxx,三位分别表示BGB ,那么 001 就是 R,010就是G,

100就是B,011就是 RG。。。以此类推,就构成了7个状态,开辟线段树,记录每个区间每种颜色的 长度,用扫描线从左往右扫描

即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define MAXN 10005
#define lson u<<1
#define rson u<<1|1
#define CLR(a,b) memset(a,0,sizeof(a))
#define LL long long

int x[MAXN<<1];
LL ans[8];

struct segment{
int x1,x2,y,val;
segment(){}
segment(int a,int b,int c,int d):x1(a),x2(b),y(c),val(d){}
bool operator < (const segment& cmp)const{
return y<cmp.y;
}
}seg[MAXN<<1];

struct Node{
int lef,rig,len[8],cnt[5];//len记录每种颜色的长度,cnt记录RGB三基色是否存在
}T[MAXN<<3];

void Build(int u,int l,int r){
T[u].lef=l;
T[u].rig=r;
CLR(T[u].len,0);
CLR(T[u].cnt,0);
if(l==r)return;
int mid=(l+r)>>1;
Build(lson,l,mid);
Build(rson,mid+1,r);
}

void PushUp(int u){
CLR(T[u].len,0);//叶子节点,长度为清0
int state=(T[u].cnt[1]>0?1:0)|(T[u].cnt[2]>0?2:0)|(T[u].cnt[4]>0?4:0);//三基色混在一起生成的状态,或操作
if(state){
T[u].len[state]+=x[T[u].rig]-x[T[u].lef-1];//记录混合色的长度
for(int i=1;i<8;i++){
if(state!=(state|i)){//判断原来是否还有其他颜色
int tmp=T[lson].len[i]+T[rson].len[i];
T[u].len[state|i]+=tmp;//新混合色长度增加
T[u].len[state]-=tmp;//原来的颜色减少
}
}
}
//如果本区间没有三基色,那么本区间的颜色长度将直接从左右儿子获得
else if(T[u].lef!=T[u].rig)for(int i=1;i<8;i++)T[u].len[i]=T[lson].len[i]+T[rson].len[i];
}

void Update(int u,int l,int r,int val){
if(l<=T[u].lef&&T[u].rig<=r){
val>0?++T[u].cnt[val]:--T[u].cnt[-val];
}
else {
if(l<=T[lson].rig)Update(lson,l,r,val);
if(r>=T[rson].lef)Update(rson,l,r,val);
}
PushUp(u);
}

int main(){

int t,n;
char color;
int x1,y1,x2,y2;

scanf("%d",&t);
for(int cas=1;cas<=t;cas++){
scanf("%d",&n);
int num=0;
for(int i=0;i<n;i++){
scanf(" %c%d%d%d%d",&color,&x1,&y1,&x2,&y2);
x[num]=x1;
seg[num++]=segment(x1,x2,y1,color=='R'?1:(color=='G'?2:4));
x[num]=x2;
seg[num++]=segment(x1,x2,y2,color=='R'?-1:(color=='G'?-2:-4));
}
sort(x,x+num);
sort(seg,seg+num);
int xnum=unique(x,x+num)-x;//去重
Build(1,1,xnum);
CLR(ans,0);
for(int i=0;i<num;i++){
int l=lower_bound(x,x+xnum,seg[i].x1)-x+1;//离散化。。
int r=lower_bound(x,x+xnum,seg[i].x2)-x;
Update(1,l,r,seg[i].val);
if(seg[i].y!=seg[i+1].y)for(int j=1;j<8;j++)ans[j]+=(LL)(seg[i+1].y-seg[i].y)*T[1].len[j];
}
printf("Case %d:\n",cas);
printf("%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n",ans[1],ans[2],ans[4],ans[3],ans[5],ans[6],ans[7]);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: