线段树求矩形并模板

来源:互联网 发布:zsysecdesk是什么软件 编辑:程序博客网 时间:2024/06/06 02:09
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define  lson(i) (idx << 1)#define  rson(i) ((idx << 1) ^ 1)using namespace std;const int N = 1010;double y[N];struct segment{double x, y1, y2;int flag;segment(){}segment(const double x, const double y1, const double y2, const int flag){this->x = x, this->y1 = y1, this->y2 = y2, this->flag = flag; }bool operator < (const segment &a) const {return x < a.x;}}line[N];struct segTree{int lc, rc, cover;double up, down, len;}arr[N * 4];void pushUp(int idx){if(arr[idx].cover > 0)arr[idx].len = arr[idx].up - arr[idx].down; else arr[idx].len = arr[lson(idx)].len + arr[rson(idx)].len;}void build(int idx, int l, int r){arr[idx].lc = l, arr[idx].rc = r;arr[idx].up = y[r], arr[idx].down = y[l];arr[idx].len = arr[idx].cover = 0;if(r - l == 1)return ;int mid = (l + r) >> 1;/**这里和普通的线段树有点不同,不能以左区间[1,mid],右区间[mid+1,r]来建树如果这样建会漏掉一些线段,比如10,20,30,40这些点来建树,按普通的建法是[10,20], [30,40],这样[20,30]这跟线段就漏掉了 所以需要左区间[l,mid],右区间[mid,r]这样来建;建出来是[10,20],[20,30],[30,40]这样就没线段漏掉了.**/build(lson(idx), l, mid);build(rson(idx), mid, r);}void update(int idx, int l, int r, int val){if(arr[idx].lc > r || l > arr[idx].rc)return ;if(arr[idx].lc >= l && arr[idx].rc <= r){arr[idx].cover += val;pushUp(idx);return ;}update(lson(idx), l, r, val);update(rson(idx), l, r, val);pushUp(idx);}int main(){int n, no = 1;while(cin >> n, n){int i, idx = 1;double x1, x2, y1, y2;for(i = 1;i <= n;i++){cin >> x1 >> y1 >> x2 >> y2;line[idx] = segment(x1, y1, y2, 1);y[idx++] = y1;line[idx] = segment(x2, y1, y2, -1);y[idx++] = y2;}sort(y + 1, y + idx);sort(line + 1, line + idx);/**以y轴建树**/ build(1, 1, idx - 1);double res = 0;for(i = 1;i < idx;i++){res += arr[1].len * (line[i].x - line[i - 1].x);/**二分出当前扫描线y1,y2的位置**/int fir = lower_bound(y + 1, y + idx, line[i].y1) - y;int sec = lower_bound(y + 1, y + idx, line[i].y2) - y;update(1, fir, sec, line[i].flag);}printf("Test case #%d\nTotal explored area: %.2f\n\n", no++, res);}return 0;}

原创粉丝点击