链接:http://poj.org/problem?id=1151
题意:求所有矩形覆盖的面积
思路:扫描线。扫描线倒是很快就看懂了,不过在线段树处理的时候弄懵了。
这道题求得比较特殊,就是求sum【1】,其他的值没有用,所以更新方式也比较奇怪= =
虽然是区间更新,lazy值并没有向下传递,而是只更新最上面(线段树)覆盖的区间,求值的时候根据当前区间的标记值,如果区间被覆盖了就是左右端点距离,如果是叶子节点且未覆盖就是0,否则就是左右子节点的和。
考虑下不向下更新是否正确:
1.父节点被覆盖:子节点的值对父节点没有影响,因为由父节点向上更新的时候直接由左右端点计算。
2.父节点未被覆盖:未被覆盖就不用向下更新,父节点的值由左右子节点求出
这道题是用端点表示的,于是用左端点表示一个区间,就和普通的线段树类似了。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof((a)))
#define For(i,a,b) for(int (i)=(a);(i) < (b);(i)++)
#define Ror(i,a,b) for(int (i)=(a);(i) > (b);(i)--)
#define mp make_pair
#define pb push_back
#define inf 0x3f3f3f3f
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
void RI (int& x){
x = 0;
char c = getchar ();
while (c == ' '||c == '\n') c = getchar ();
bool flag = 1;
if (c == '-'){
flag = 0;
c = getchar ();
}
while (c >= '0' && c <= '9'){
x = x * 10 + c - '0';
c = getchar ();
}
if (!flag) x = -x;
}
void RII (int& x, int& y){RI (x), RI (y);}
void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);}
const int maxn = 100100;
int ff[maxn<<2];
double sum[maxn<<2];
double xx[210];
void pushup(int rt,int l,int r){
if(ff[rt])sum[rt] = xx[r] - xx[l-1];
else if(l == r)sum[rt] = 0;
else sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void update(int L,int R,int c,int l,int r,int rt){
//[L,R]更新区间,[l,r]当前区间
if(L <= l&&r <= R){
ff[rt] += c;
pushup(rt,l,r);
return ;
}
int m = (l + r) >> 1;
if(R <= m)update(L,R,c,lson);
else if(L > m)update(L,R,c,rson);
else {
update(L,m,c,lson);
update(m+1,R,c,rson);
}
pushup(rt,l,r);
}
struct Seg{
double l,r;
double h;
int ff;
}seg[210];
bool cmp(Seg a,Seg b){
return a.h < b.h;
}
int main(){
//freopen("test.txt","r",stdin);
int n;
int cas = 1;
while(1){
RI(n);
if(n == 0)break;
For(i,0,n){
double xa,ya,xb,yb;
cin>>xa>>ya>>xb>>yb;
seg[2*i] = (Seg){xa,xb,ya,1};
seg[2*i+1] = (Seg){xa,xb,yb,-1};
xx[2*i] = xa;
xx[2*i+1] = xb;
}
sort(seg,seg+n*2,cmp);
sort(xx,xx+n*2);
int siz = unique(xx,xx+n*2) - xx;
//For(i,0,siz+1)cout<<xx[i]<<' ';cout<<endl;
mem(sum,0);
mem(ff,0);
double ans = 0;
For(i,0,2*n-1){
int l = lower_bound(xx,xx+siz,seg[i].l)-xx+1;
int r = lower_bound(xx,xx+siz,seg[i].r)-xx;
update(l,r,seg[i].ff,1,siz-1,1);//cout<<sum[1]<<' '<<l<<' '<<r<<endl;
ans += sum[1]*(seg[i+1].h - seg[i].h);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n",cas ++,ans);
}
return 0;
}