/* * 这个跟昨天写的矩形面积的并是差不多的,而且我译开始还是写的一样的,sample都相差那么一点的 * 看了别人的加了moresum就OK那里的更新还是有点不理解的,转下一下的供自己回忆 题意:求矩形的交的面积!覆盖两次或以上! 将每个矩形的两条纵向边看成两个事件点,遇到左端点,插入该纵向边,遇到右节点,删除该边! 对所有y坐标进行离散化!进行线段树的插入和更新操作! 其实这道题跟求矩形的并的面积类似。不同的是更新每个节点覆盖长度的操作! 我采用cover,once,more这三个变量来维护线段树。 cover:表示该节点被覆盖多少次。 once:表示该节点表示的长度中,被覆盖1次以上的长度。 more:表示该节点表示的长度中,被覆盖2次以上的长度。 插入操作:找到属于当前边范围的节点,cover+=v。v是个标志,表示是插入边或删除边。 更新操作比较复杂。 当前节点被覆盖两次或以上,那么该点的once和more值都是节点表示的长度。 当前节点被覆盖一次,那么once等于节点的长度,而more等于左右子树被覆盖一次以上的长度的和。 当节点没有被覆盖,那么once等于左右子树的once值的和,more等于左右子树more的值的和。 http://hi.baidu.com/ccbow/blog/item/b1d17a139ae9e329dc54014d.html */ #include <iostream> #include <cstdio> #include <algorithm> #define LL(x) ((x) << 1) #define RR(x) ((x) << 1 | 1) using namespace std; const int N = 1555; struct Seg_tree{ int l, r; int st; double sum; double moresum; // 加了一个这个就AC了 int mid(){ return (l + r) >> 1; } }tree[6 * N]; struct Line{ double high; double l, r; int st; }line[2 * N]; double pos[2 * N]; int len; inline bool cmp(const Line &a, const Line &b){ return a.high < b.high; } inline void Build(int l ,int r, int node){ tree[node].l = l; tree[node].r = r; tree[node].st = 0; tree[node].sum= 0; tree[node].moresum = 0; if(l == r) return; int mid = (l + r) >> 1; Build(l, mid, LL(node)); Build(mid + 1, r, RR(node)); } inline void Update(int node){ if(tree[node].st ){ tree[node].sum = pos[tree[node].r + 1] - pos[tree[node].l]; } else if(tree[node].l == tree[node].r){ tree[node].sum = 0; } else{ tree[node].sum = tree[LL(node)].sum + tree[RR(node)].sum; } if(tree[node].st > 1){ // 加了一个moresum tree[node].moresum = pos[tree[node].r + 1] - pos[tree[node].l]; } else if(tree[node].l == tree[node].r){ tree[node].moresum = 0; }else if(tree[node].st > 0){ tree[node].moresum = tree[LL(node)].sum + tree[RR(node)].sum; }else{ tree[node].moresum = tree[LL(node)].moresum + tree[RR(node)].moresum; } } inline void Update(int l, int r, int node, int st){ if(l <= tree[node].l && tree[node].r <= r){ tree[node].st += st; Update(node); return ; } int mid = tree[node].mid(); if(r <= mid){ Update(l, r, LL(node), st); } else if(l > mid){ Update(l, r, RR(node), st); } else{ Update(l, mid, LL(node), st); Update(mid + 1, r, RR(node), st); } Update(node); } inline int Bin(double x){ int low = 0; int high = len - 1; //puts("Bin"); while(low <= high){ int mid = (low + high) >> 1; if(pos[mid] == x) return mid; if(pos[mid] < x){ low = mid + 1; } else{ high = mid - 1; } } return -1; } int main(){ int t; scanf("%d", &t); while(t--){ int n; scanf("%d", &n); double x1, y1, x2, y2; int m = 0; for(int i = 0; i < n; i++){ scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2); line[m].high = y1; line[m].st = 1; line[m + 1].high = y2; line[m + 1].st = -1; pos[m] = line[m].l = line[m + 1].l = x1; pos[m + 1] = line[m].r = line[m + 1].r = x2; m += 2; } sort(line, line + m, cmp); sort(pos, pos + m); //printf("m :: %d/n", m); len = 0; for(int i = 0; i < m; i++){ if(i == 0 || pos[i - 1] != pos[i]) pos[len++] = pos[i]; } Build(0, len - 1, 1); //printf("len :: %d/n", len); double ans = 0; for(int i = 0; i < m - 1; i++){ int l = Bin(line[i].l); int r = Bin(line[i].r) - 1; //printf("l :: %d r :: %d/n", l, r); Update(l, r, 1, line[i].st); ans += tree[1].moresum * (line[i + 1].high - line[i].high); } printf("%0.2lf/n", ans); // 早Eclipse 下C++ ans + 0.001 才能4舍5入的 } }