Codeforces 610D Vika and Segments 【线段树扫描线 求面积并】

D. Vika and Segments
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Vika has an infinite sheet of squared paper. Initially all squares are white. She introduced a two-dimensional coordinate system on this sheet and drew n black horizontal and vertical segments parallel to the coordinate axes. All segments have width equal to 1 square, that means every segment occupy some set of neighbouring squares situated in one row or one column.

Your task is to calculate the number of painted cells. If a cell was painted more than once, it should be calculated exactly once.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the number of segments drawn by Vika.

Each of the next n lines contains four integers x1y1x2 and y2 ( - 109 ≤ x1, y1, x2, y2 ≤ 109) — the coordinates of the endpoints of the segments drawn by Vika. It is guaranteed that all the segments are parallel to coordinate axes. Segments may touch, overlap and even completely coincide.

Output

Print the number of cells painted by Vika. If a cell was painted more than once, it should be calculated exactly once in the answer.

Sample test(s)
input
3
0 1 2 1
1 4 1 2
0 3 2 3
output
8
input
4
-2 -1 2 -1
2 1 -2 1
-1 -2 -1 2
1 2 1 -2
output
16
Note

In the first sample Vika will paint squares (0, 1)(1, 1)(2, 1)(1, 2)(1, 3)(1, 4)(0, 3) and (2, 3).



题意:给n条要么垂直要么平行于坐标轴的宽度为1的线段,问你这些线段包含点的个数。


线段树 + 离散化+ 扫描线,确定好坐标就可以了。


AC代码:


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (200000+10)
#define MAXM (500000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
struct Tree
{
    int l, r;
    double sum;
    int cover;
};
Tree tree[MAXN<<2];
struct Node
{
    double x1, x2, y;
    int cover;
};
Node node[MAXN];
bool cmp(Node a, Node b){
    return a.y < b.y;
}
void build(int o, int l, int r)
{
    tree[o].l = l, tree[o].r = r;
    tree[o].sum = tree[o].cover = 0;
    if(l == r)
        return ;
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
}
double rec[MAXN];
void PushUp(int o)
{
    if(tree[o].cover)
        tree[o].sum = rec[tree[o].r+1] - rec[tree[o].l];
    else
    {
        if(tree[o].l == tree[o].r)
            tree[o].sum = 0;
        else
            tree[o].sum = tree[ll].sum + tree[rr].sum;
    }
}
void update(int L, int R, int o, int v)
{
    if(L <= tree[o].l && R >= tree[o].r)
    {
        tree[o].cover += v;
        PushUp(o);
        return ;
    }
    int mid = (tree[o].l + tree[o].r) >> 1;
    if(R <= mid)
        update(L, R, ll, v);
    else if(L > mid)
        update(L, R, rr, v);
    else
    {
        update(L, mid, ll, v);
        update(mid+1, R, rr, v);
    }
    PushUp(o);
}
int Find(int l, int r, double val)
{
    while(r >= l)
    {
        int mid = (l + r) >> 1;
        if(rec[mid] == val)
            return mid;
        else if(rec[mid] > val)
            r = mid - 1;
        else
            l = mid + 1;
    }
    return -1;
}
int main()
{
    int n; Ri(n);
    int k = 1;
    double x1, y1, x2, y2;
    for(int i = 0; i < n; i++)
    {
        scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
        if(x1 == x2)
        {
            if(y1 > y2)
                swap(y1, y2);
        }
        if(y1 == y2)
        {
            if(x1 > x2)
                swap(x1, x2);
        }
        x2++; y2++;
        node[k].x1 = x1; node[k].x2 = x2;
        node[k].y = y1;  node[k].cover = 1;
        rec[k++] = x1;

        node[k].x1 = x1; node[k].x2 = x2;
        node[k].y = y2;  node[k].cover = -1;
        rec[k++] = x2;
    }
    sort(node+1, node+k, cmp);
    sort(rec+1, rec+k);
    int R = 2;
    for(int i = 2; i < k; i++)
        if(rec[i] != rec[i-1])
            rec[R++] = rec[i];
    sort(rec+1, rec+R);
    build(1, 1, R-1);
    double ans = 0;
    for(int i = 1; i < k-1; i++)
    {
        int x = Find(1, R-1, node[i].x1);
        int y = Find(1, R-1, node[i].x2);
        if(x <= y-1) update(x, y-1, 1, node[i].cover);
        ans += tree[1].sum * (node[i+1].y - node[i].y);
    }
    printf("%.0lf\n", ans);
    return 0;
}


你可能感兴趣的:(线段树,离散化,扫描线,codeforces)