POJ1177(扫描线求周长并)

题意:。。求周长并。。。

解析:参考求面积并

图借鉴自:https://www.cnblogs.com/shuaiwhu/archive/2012/04/22/2464876.html

  自下而上扫描 首先 加GH 接着 加 Node[1].numseg * 2 *(Edge[i+1].y - Edge[i].y)即两条竖边   然后 加 BD 但这时要减去GH  因为 LN = GH 重复加了一次

 依次推理

与面积并不同的是 最上面的边不要忘了加上。。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 10010, INF = 0x7fffffff;
int X[maxn];

struct node{
    int l, r, w; // l 和 r 分别为线段树的左右端点  w记录边重叠的情况
    int numseg;  // 记录竖边的对数
    int lx, rx, sum;  // sum代表当前区间线段的长度,lx和rx为线段的真实端点
    bool lcover, rcover;  // 标记当前区间的左右端点 与 numseg有关
}Node[maxn*4];

struct edge{  // 存边
    int lxx, rxx, y;
    int f;
}Edge[maxn];

int cmp(edge a, edge b)
{
    return a.y < b.y;
}

void build(int k, int ll, int rr)
{
    Node[k].l = ll, Node[k].r = rr;
    Node[k].lx = X[ll];
    Node[k].rx = X[rr];
    Node[k].w = Node[k].numseg = 0, Node[k].sum = 0;
    Node[k].lcover = Node[k].rcover = false;
    if(ll + 1 == rr) return;
    int m = (ll + rr) / 2;
    build(k*2, ll, m);
    build(k*2+1, m, rr);
}

void down(int k)
{
    if(Node[k].w > 0)
    {
        Node[k].sum = Node[k].rx - Node[k].lx;
        Node[k].numseg = 1;
        Node[k].lcover = Node[k].rcover = true;
        return;
    }
    if(Node[k].l + 1 == Node[k].r)
    {
        Node[k].sum = 0;
        Node[k].numseg = 0;
        Node[k].lcover = Node[k].rcover = false;
    }
    else
    {
        Node[k].sum = Node[k*2].sum + Node[k*2+1].sum;
        Node[k].lcover = Node[k*2].lcover, Node[k].rcover = Node[k*2+1].rcover;
        Node[k].numseg = Node[k*2].numseg + Node[k*2+1].numseg;
        if(Node[k*2].rcover && Node[k*2+1].lcover) Node[k].numseg--;   //注意这里是左区间的右端点 和 右区间的左端点
    }
}

void update(int k, edge e)
{
    if(Node[k].lx == e.lxx && Node[k].rx == e.rxx)
    {
        Node[k].w += e.f;
        down(k);
        return;
    }
    if(e.rxx <= Node[k*2].rx) update(k*2, e);
    else if(e.lxx >= Node[k*2+1].lx) update(k*2+1, e);
    else
    {
        edge temp = e;
        temp.rxx = Node[k*2].rx;
        update(k*2, temp);
        temp = e;
        temp.lxx = Node[k*2+1].lx;
        update(k*2+1, temp);
    }
    down(k);
}


int main()
{
    int n, cnt = 0;
    scanf("%d",&n);
    for(int i=0; i<n; i++)
    {
        int x1, x2, y1, y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        Edge[++cnt].lxx = x1, Edge[cnt].rxx = x2, Edge[cnt].y = y1, Edge[cnt].f = 1;
        X[cnt] = x1;
        Edge[++cnt].lxx = x1, Edge[cnt].rxx = x2, Edge[cnt].y = y2, Edge[cnt].f = -1;
        X[cnt] = x2;
    }
    sort(Edge+1, Edge+cnt+1, cmp);
    sort(X+1, X+cnt+1);
    int m = unique(X+1, X+cnt+1) - (X+1);
    build(1, 1, m);
    int ret = 0, last = 0;
    for(int i=1; i<cnt; i++)
    {
        update(1, Edge[i]);
        ret += abs(Node[1].sum - last); // 横边
        ret += Node[1].numseg * 2 * (Edge[i+1].y - Edge[i].y);  // 加竖边
        last = Node[1].sum;
    }
    update(1, Edge[cnt]);
    ret += abs(Node[1].sum - last);

    printf("%d\n",ret);

    return 0;
}

 

posted @ 2018-07-05 20:34  WTSRUVF  阅读(282)  评论(0编辑  收藏  举报