[HDU1542]Atlantis

来源:互联网 发布:apache windows 64位 编辑:程序博客网 时间:2024/05/17 07:56

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1542


与以往线段树不同的地方是区间[l, r]表示的是线段为[l, r + 1],因为比如说对区间[1, 4]建树,它的儿子分别为[1, 2]和[3, 4],如果直接用这个区间表示线段,则2到3这部分没有了。特别的,当l==r时,结点[l, r]是指一条长度为1的线段,它起点为l,终点为l + 1。


#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<map>#include<set>#include<vector>#include<utility>using namespace std;#define LL long long#define FUCK cout << "Ca!" << endl;#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1const double eps = 1e-8;const int maxn = 2222;struct Square{    double x1, y1, x2, y2;}sq[maxn];struct Segment{    double h;    int l, r, mark;}e[maxn << 1];double sum[maxn << 2],  yy[maxn << 1], Y[maxn << 1];int cal[maxn << 2], cnt;bool cmp(Segment a, Segment b){    return a.h < b.h;}void build(int l, int r, int rt){    cal[rt] = 0;    sum[rt] = 0;    if (l == r) return;    int mid = (l + r) >> 1;    build(lson);    build(rson);}double dcmp(double num){    if (fabs(num) < eps) return 0;    if (num < 0) return -1;    else return 1;}double Bin(double num){    int l = 1, r = cnt;    while (l <= r)    {        int mid = (l + r) >> 1;        if (dcmp(yy[mid] - num) < 0) l = mid + 1;        else r = mid - 1;    }    return l;}void Edge(int i, double h, double l, double r, int mark){    e[i].h = h;    e[i].mark = mark;    e[i].l = Bin(l);    e[i].r = Bin(r);}void pushup(int rt, int l, int r){    if (cal[rt]) sum[rt] = yy[r + 1] - yy[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 mark, int l, int r, int rt){    if (L <= l && R >= r)    {        cal[rt] += mark;        pushup(rt, l, r);        return;    }    int mid = (l + r) >> 1;    if (L <= mid) update(L, R, mark, lson);    if (R > mid) update(L, R, mark, rson);    pushup(rt, l, r);}int main(){    int n, kase = 0;    while (cin >> n)    {        if (n == 0) break;        ++kase;        int i;        //把y坐离散化        for (i = 0; i < n; i++)        {            cin >> sq[i].x1 >> sq[i].y1 >> sq[i].x2 >> sq[i].y2;            Y[i * 2] = sq[i].y1;            Y[i * 2 + 1] = sq[i].y2;        }        sort(Y, Y + 2 * n);        cnt = 1;        yy[cnt] = Y[0];        for (i = 1; i < 2 * n; i++)        {           if (fabs(Y[i] - Y[i - 1]) > eps) yy[++cnt] = Y[i];        }        //建树        build(1, cnt - 1, 1);        //把矩形拆成上下两边线段并换Y轴排序        for (i = 0; i < n; i++)        {            Edge(i * 2, sq[i].x1, sq[i].y1, sq[i].y2, 1);            Edge(i * 2 + 1, sq[i].x2, sq[i].y1, sq[i].y2, -1);        }        sort(e, e + 2 * n, cmp);        //计算面积        double ans = 0;        update(e[0].l, e[0].r - 1, e[0].mark, 1, cnt, 1);        for (i = 1; i < 2 * n; i++)        {            ans += sum[1] * (e[i].h - e[i - 1].h);            update(e[i].l, e[i].r - 1, e[i].mark, 1, cnt, 1);        }        cout << "Test case #" << kase << endl;        printf("Total explored area: %.2lf\n\n", ans);    }}


原创粉丝点击