POJ1177 Picture 线段树+离散化+扫描线

求最终的覆盖图形周长,写这种代码应该短而精确,差的比较远

/*
Problem: 1177        User: 96655
Memory: 348K        Time: 32MS
Language: C++        Result: Accepted
*/
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <algorithm>
using namespace std;
const int maxn=10010;
struct Node
{
    int s,t,num,len,cover;
    bool lb,rb;
    void change(int o)
    {
        cover+=o;
        if(cover==0)len=lb=rb=num=0;
        else len=t-s,lb=1,rb=1,num=1;
    }
} node[maxn<<2];
struct Line
{
    int x,y1,y2,flag;
    void fun(int a,int b,int c,int d)
    {
        x=a,y1=b,y2=c,flag=d;
    }
    bool operator<(const Line &e)const
    {
        if(x==e.x)
            return flag>e.flag;
        return x<e.x;
    }
} line[maxn];
int y[maxn];
void build(int rt,int l,int r)
{
    node[rt].s=y[l];
    node[rt].t=y[r];
    node[rt].num=node[rt].len=node[rt].cover=0;

    if(l+1==r)return;
    int m=(l+r)>>1;
    build(rt*2,l,m);
    build(rt*2+1,m,r);
}
void update_line(int rt)
{
    node[rt].lb=node[rt*2].lb;
    node[rt].rb=node[rt*2+1].rb;
    node[rt].num=node[rt*2].num+node[rt*2+1].num-node[rt*2].rb*node[rt*2+1].lb;
}
void update_len(int rt)
{
    node[rt].len=node[rt*2].len+node[rt*2+1].len;
}
void update(int rt,int l,int r,Line e)
{
    if(l+1==r)
    {
        node[rt].change(e.flag);
        return;
    }
    int m=(l+r)>>1;
    if(e.y1<node[rt*2].t)update(rt*2,l,m,e);
    if(e.y2>node[rt*2+1].s)update(rt*2+1,m,r,e);
    update_len(rt);
    update_line(rt);
}
int main()
{
    int n,x1,x2,y1,y2,cnt=0,d=1;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        line[++cnt].fun(x1,y1,y2,1);
        y[cnt]=y1;
        line[++cnt].fun(x2,y1,y2,-1);
        y[cnt]=y2;
    }
    sort(y+1,y+1+cnt);
    sort(line+1,line+1+cnt);
    for(int i=2; i<=cnt; ++i)
        if(y[i]!=y[i-1])y[++d]=y[i];
    build(1,1,d);
    int perimeter=0;
    int now_len=0;
    int now_num=0;
    for(int i=1; i<=cnt; ++i)
    {
        update(1,1,d,line[i]);
        if(i>1)perimeter+=2*now_num*(line[i].x-line[i-1].x);
        perimeter+=abs(node[1].len-now_len);
        now_num=node[1].num;
        now_len=node[1].len;
    }
    printf("%d\n",perimeter);
    return 0;
}
View Code

 

posted @ 2015-11-11 16:16  shuguangzw  阅读(117)  评论(0编辑  收藏  举报