您的位置:首页 > 其它

CSU 1292 Rectangles Intersection

2013-05-24 18:50 381 查看
  原题链接:http://122.207.68.93/OnlineJudge/problem.php?id=1292

  线段树+扫描线。这道题是典型的矩形面积并问题,乍一看109 * 109 * 105 超了long long,但这个无关紧要,其实如果总面积>1018 可以直接判断肯定有相交的面积了,这么一来,就是裸模版题了,贴膜板:

#include "cstdio"
#include "iostream"
#include "algorithm"
#define lson cur<<1
#define rson cur<<1|1
using namespace std;
typedef long long LL;
const int maxn = 200000 + 5;
const int root = 1;
struct seg            //扫描线结构体
{
int x, y1, y2; //扫描线数据  x横坐标  y1,y2,上下顶点
short flag;       //标记是进入的还是出来的(对于一个矩形所产生的两条扫描线来说)
seg() {};
seg(int a, int b, int c, short d):x(a), y1(b), y2(c), flag(d) {}
inline friend bool operator <(seg a, seg b)
{
return a.x < b.x;    //用于sort
}
} ss[maxn];
int m;               //扫描线总数
int y[maxn];    //离散值-->实际值
struct node               //线段树结构体 (加入的是扫描线(纵向))
{
int l, r, cover;      //左右范围(实际上没有用),cover:是否完全覆盖
int yl, yr, len;   //实际范围和长度
node() {}
node(int a, int b, int c, int d, short f, int g)
{
l = a, r = b, yl = c, yr = d, cover = f, len = g;
}
} a[maxn << 2];
inline void build(int cur, int l, int r)       //建立线段树
{
a[cur] = node(l, r, y[l], y[r], 0, 0);
if (l+1 == r) return ;
int mid = (l+r) >> 1;
build(lson, l, mid);
build(rson, mid, r);
}

inline void pushup(int cur)                          //计算当前cur结点覆盖的长度(纵向)
{
if (a[cur].cover > 0) a[cur].len = a[cur].yr - a[cur].yl;  //当前结点被完全覆盖
else if (a[cur].l+1 == a[cur].r) a[cur].len = 0; //叶节点但已经被去除掉了(cover<=0)
else  a[cur].len = a[lson].len + a[rson].len;    //自身未被完全覆盖,向子节点求助
}

inline void updata(int cur, seg b)                  //更新i.e加入边操作
{
if (b.y1 == a[cur].yl && b.y2 == a[cur].yr)
{
//被加入的边完全覆盖
a[cur].cover += b.flag;                     //是否被抛弃
pushup(cur);                                //计算长度
return;
}
if (b.y2 <= a[rson].yl) updata(lson, b);
else if (b.y1 >= a[lson].yr) updata(rson, b);
else
{
seg tmp = b;                                //将b拆开付给lson rson
tmp.y2 = a[lson].yr;
updata(lson, tmp);
tmp = b, tmp.y1 = a[rson].yl;
updata(rson, tmp);
}
pushup(cur);
return;
}
int main()
{
int t, n;
int x1, x2, y1, y2;
LL area;
cin >> t;
while(t--)
{
m = 0;
scanf("%d", &n);
area = 0;
for (int i = 1; i <= n; i ++)
{
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
area += (LL)(x2 - x1) * (LL)(y2 - y1);
ss[++m] = seg(x1, y1, y2, 1), y[m] = y1;            //建立扫描线
ss[++m] = seg(x2, y1, y2, -1), y[m] = y2;
}
if(area < 0 || area > 1000000000000000000ll)
{
cout << "Bad" << endl;
continue;
}
sort(ss+1,ss+1+m);
sort(y+1,y+1+m);          //离散化

build(root, 1, m);                                                //建树
LL sum(0);
for (int i = 1; i < m; i++)                                    //依次加边
{
updata(root, ss[i]);
sum += (LL)a[root].len * (LL)(ss[i+1].x - ss[i].x);   //计算此时面积
}
if(area == sum)
puts("Good");
else
puts("Bad");
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: