hdu 1255 面积交

来源:互联网 发布:开机client mac addr 编辑:程序博客网 时间:2024/05/01 01:57

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255

方法:离散化,线段树,扫描线

代码:

/**以y轴为扫描线然后用x[]记录下所有的x坐标,并对x坐标去重对于每一条扫描线xl, xr都二分找到在数组x[]的下标在用线段树更新的时候每次找到更新可以的区间的时候用pushdown(),更新到底并且用pushup()往上更新*/#include <iostream>#include <cstdio>#include <algorithm>using namespace std;#define maxn 2005struct Line{      double xl, xr, y;      int cover;      Line(){}      Line(double xl, double xr, double y, int cover):            xl(xl), xr(xr), y(y), cover(cover){}      bool operator < (const Line& b)const      {            return y<b.y;      }}line[maxn];double x[maxn];struct node{      int l, r, cover;      double sum;}v[maxn<<2];void build(int l, int r, int n){      v[n].l = l, v[n].r = r;      v[n].sum = 0;      v[n].cover = 0;      if (l==r)            return ;      int mid = (l+r) >> 1;      build(l, mid, n<<1);      build(mid+1, r, n<<1|1);}int find(double key, int n){      int l = 1, r = n, mid;      while (l<=r)      {            mid = (l+r) >> 1;            if (x[mid]==key)                  return mid;            else if (x[mid]>key)                  r = mid-1;            else                  l = mid+1;      }}void pushup(int n){      v[n].sum = v[n<<1].sum + v[n<<1|1].sum;}void pushdown(int l, int r, int n, int cover){      v[n].cover += cover;      if (l==r)      {            if (v[n].cover>1)                  v[n].sum = x[r+1] - x[r];            else                  v[n].sum = 0;            return ;      }      int mid = (l + r) >> 1;      pushdown(l, mid, n<<1, cover);      pushdown(mid+1, r, n<<1|1, cover);      pushup(n);}void update(int n, int l, int r, int cover){      if (l<=v[n].l && v[n].r<=r)      {            pushdown(v[n].l, v[n].r, n, cover);//更新到底,然后从底统计上来            return ;      }      int mid = (v[n].l + v[n].r) >> 1;      if (r<=mid)            update(n<<1, l, r, cover);      else if (l>mid)            update(n<<1|1, l, r, cover);      else      {            update(n<<1, l, mid, cover);            update(n<<1|1, mid+1, r, cover);      }      pushup(n);}int main(){      int ncase, n;      scanf("%d", &ncase);      while (ncase--)      {            scanf("%d", &n);            int num = 0;            for (int i=0; i<n; ++i)            {                  double x1, x2, y1, y2;                  scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);                  line[++num] = Line(x1, x2, y1, 1);                  x[num] = x1;                  line[++num] = Line(x1, x2, y2, -1);                  x[num] = x2;            }            sort(x+1, x+num+1);            sort(line+1, line+num+1);            n = 1;            for (int i=2; i<=num; ++i)//去除相同的点                  if (x[i]>x[i-1])                        x[++n] = x[i];            double ans = 0;            build(1, n, 1);            for (int i=1; i<num; ++i)            {                  int l = find(line[i].xl, n);                  int r = find(line[i].xr, n)-1;                  update(1, l, r, line[i].cover);                  ans += v[1].sum * (line[i+1].y - line[i].y);            }            printf("%.2f\n", ans);      }      return 0;}
#include <iostream>#include <cstdio>#include <algorithm>using namespace std;#define maxn 2005struct Line{      double xl, xr, y;      int cover;      Line(){}      Line(double xl, double xr, double y, int cover):            xl(xl), xr(xr), y(y), cover(cover){};      bool operator < (const Line& b)const      {            return y<b.y;      }}line[maxn];double x[maxn];struct node{      int l, r, cover;      double sum;//被覆盖两次及两次以上的长度      double cnt;//被覆盖一次及一次以上的长度      double xl, xr;}v[maxn<<2];int find(double key, int n){      int l = 1, r = n, mid;      while (l<=r)      {            mid = (l+r) >> 1;            if (x[mid]==key)                  return mid;            else if (x[mid]>key)                  r = mid-1;            else                  l = mid+1;      }}void build(int l, int r, int n){      v[n].l = l, v[n].r = r;      v[n].xl = x[l], v[n].xr = x[r];      v[n].cover = 0;      v[n].sum = v[n].cnt = 0;      if (l+1==r)//这里不是l==r            return;      int mid = (v[n].l + v[n].r) >> 1;      build(l, mid, n<<1);      build(mid, r, n<<1|1);//这里不是mid+1}void pushup(int n)//往上更新时分情况考虑{      if (v[n].cover>=2)      {            v[n].sum = v[n].xr - v[n].xl;            v[n].cnt = v[n].xr - v[n].xl;      }      else if (v[n].cover == 1)      {            v[n].cnt = v[n].xr - v[n].xl;            if (v[n].l+1==v[n].r)                  v[n].sum = 0;            else                  v[n].sum = v[n<<1].cnt + v[n<<1|1].cnt;//这里注意      }      else      {            if (v[n].l+1==v[n].r)                  v[n].sum = v[n].cnt = 0;            else            {                  v[n].sum = v[n<<1].sum + v[n<<1|1].sum;                  v[n].cnt = v[n<<1].cnt + v[n<<1|1].cnt;            }      }}void update(int n, int l, int r, int cover){      if (l<=v[n].l && v[n].r<=r)      {            v[n].cover += cover;            pushup(n);            return ;      }      int mid = (v[n].l + v[n].r) >> 1;      if (r<=mid)            update(n<<1, l, r, cover);      else if (l>=mid)            update(n<<1|1, l, r, cover);      else      {            update(n<<1, l, mid, cover);            update(n<<1|1, mid, r, cover);      }      pushup(n);}int main(){      int ncase, n;      scanf("%d", &ncase);      while (ncase--)      {            scanf("%d", &n);            int num = 0;            for (int i=0; i<n; ++i)            {                  double x1, x2, y1, y2;                  scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);                  line[++num] = Line(x1, x2, y1, 1);                  x[num] = x1;                  line[++num] = Line(x1, x2, y2, -1);                  x[num] = x2;            }            sort(x+1, x+num+1);            sort(line+1, line+num+1);            n = 1;            for (int i=2; i<=num; ++i)                  if (x[i]>x[i-1])                        x[++n] = x[i];            double ans = 0;            build(1, n, 1);            for (int i=1; i<num; i++)            {                  int l = find(line[i].xl, n);                  int r = find(line[i].xr, n);                  update(1, l, r, line[i].cover);                  ans += v[1].sum * (line[i+1].y - line[i].y);            }            printf("%.2f\n", ans);      }      return 0;}

原创粉丝点击