/*
hdu 3265 Posters 線段樹+掃描線
用一些中間有矩形洞的矩形海報去糊窗戶
文被覆蓋的面積
線段樹+掃描線
可以簡單看一下掃面線,這裏只是簡單應用(因爲邊只有水平、垂直兩種,所以不用y=y+1地掃,也不用在求交點)
在水平方向上做線段樹,進行掃描
每個矩形記錄兩條邊,底邊給這段塗上顏色,頂邊把顏色去掉
對於大數據,c++的容器的速度還真不敢恭維,以後還是用c吧
改c的時候讀x3的時候忘了&
其中還出現幾次 Runtime Error(STACK_OVERFLOW) 是因爲maxx寫成了5555
*/
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
const int maxx=55555;
struct node
{
__int64 sum,color;
}tree[maxx<<3];
struct seg
{
int x1,x2,y,color;
seg(int a,int b,int c,int d):x1(a),x2(b),y(c),color(d){}
bool operator < (const seg &t)const{
return y < t.y;
}
};
void pushUp(int no,int l,int r)
{
if(tree[no].color) tree[no].sum=r-l+1;
else if(l==r) tree[no].sum=0;
else tree[no].sum=tree[no<<1].sum+tree[no<<1|1].sum;
}
void update(int x1,int x2,int color,int l,int r,int no)
{
if(x1<=l&&r<=x2)//整個區間塗上顏色或去掉顏色
{
tree[no].color+=color;
pushUp(no,l,r);//更新所塗長度
return;
}
int m=(l+r)>>1;//左右分別
if(x1<=m) update(x1,x2,color,l,m,no<<1);//注意等號
if(x2>m) update(x1,x2,color,m+1,r,no<<1|1);
pushUp(no,l,r);
}
int main()
{
int n,x1,x2,x3,x4,y1,y2,y3,y4,i;
while(cin>>n,n)
{
vector<seg> v;
for(i=1;i<=n;++i)
{
cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;
if(x1<x3)//拆成四個矩形
{
v.push_back(seg(x1,x3,y1,1));//底邊給這段塗上顏色,
v.push_back(seg(x1,x3,y2,-1));//頂邊把顏色去掉
}
if(x4<x2)
{
v.push_back(seg(x4,x2,y1,1));
v.push_back(seg(x4,x2,y2,-1));
}
if(y1<y3)
{
v.push_back(seg(x3,x4,y1,1));
v.push_back(seg(x3,x4,y3,-1));
}
if(y4<y2)
{
v.push_back(seg(x3,x4,y4,1));
v.push_back(seg(x3,x4,y2,-1));
}
}
sort(v.begin(),v.end());//從小到大排序,從小的開始掃描
memset(tree,0,sizeof(tree));
__int64 ret=0;
int end=v.size();
for(i=0;i<end-1;++i)
{
if(v[i].x2>v[i].x1)
update(v[i].x1,v[i].x2-1,v[i].color,0,maxx,1);//對每條邊 經行 塗顏色或去顏色 注意第二個參數-1 左閉右開,防止一個點算兩次
ret+=tree[1].sum*(v[i+1].y-v[i].y);//根據所塗長度 及 高度差 算面積
}
printf("%I64d\n",ret);
}
return 0;
}
hdu 3265 Posters 線段樹+掃描線
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.