HDOJ-1542 Atlantis

来源:互联网 发布:fifa17球员数据 编辑:程序博客网 时间:2024/06/07 19:42
r + 1, r - 1,用来处理线段跨子树的情况
比如按X排序后的结果10,15, 20, 25.5 离散化后为0,1,2,3
如果线段为0-2,而一次划分0-1,2-3
r-1 保证取到0-1, r+1保证取到 2
或者更极端的可能线段为1, 2
r-1保证取到1, 而r+1保证取到2

还有可能线段为0-3,那么这样也能保证能取到。

更多线段树姿势请到点击打开链接,我觉得写的最好线段树模版。

#include <cstdio>#include <cstring>#include <algorithm>#define lson l, m, rt<<1#define rson m + 1, r, rt<<1|1using namespace std;const int maxn = 2222;struct Seg{double l, r, h;int s;Seg(){}Seg(double a, double b, double c, int d): l(a), r(b), h(c), s(d){}bool operator <(const Seg &tmp)const{return h < tmp.h;}}ss[maxn<<2];int cnt[maxn<<2];double sum[maxn<<2]; double X[maxn];void pushUp(int l, int r, int rt){if(cnt[rt])sum[rt] = X[r+1] - X[l];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){if(L <= l && r <= R){cnt[rt] += c;pushUp(l, r, rt);return ;}int m = (l + r) >> 1;if(L <= m)update(L, R, c, lson);if(m < R)update(L, R, c, rson);pushUp(l, r, rt);}int Bin(double key, int k){int l = 0, r = k - 1; while(l <= r){int m = (l + r) >>1;if(X[m] == key)return m;if(key < X[m]) r = m - 1;else l = m + 1;}return -1;}int main(){int n;int cas = 1;while(~scanf("%d",&n)&&n){int i, j;double a, b, c, d;int m = 0;for(i = 0; i < n; i ++){scanf("%lf%lf%lf%lf", &a, &b, &c, &d);ss[m] = Seg(a, c, b, 1);X[m++] = a;ss[m] = Seg(a, c, d, -1);X[m++] = c;}sort(X, X + m);sort(ss, ss + m);j = 1;memset(sum, 0, sizeof(sum));memset(cnt, 0, sizeof(cnt));for(i = 1; i < m; i++)if(X[i] != X[i-1]) X[j++] = X[i];double ret = 0;for(i = 0; i < m - 1; i++){int l = Bin(ss[i].l, j);int r = Bin(ss[i].r, j) - 1;update(l, r, ss[i].s, 0, j - 1, 1);ret += sum[1] * (ss[i+1].h - ss[i].h);}printf("Test case #%d\nTotal explored area: %.2lf\n\n",cas,ret);cas ++;}return 0;}


0 0