poj 1177 Picture 线段树加扫描线

来源:互联网 发布:大津算法 matlab 编辑:程序博客网 时间:2024/06/09 23:38
求矩形周长的并
之前做过一个求矩形面积并的题目
用到了扫描线这种思想
这个题目可以照搬,作两次扫描线,一次x轴,一次y轴,同样标记入边,出边,当边是最外面的边时
周长就加上这条边的长度的两倍,入边标志为1,出边为-1,当加入边之后count==0,则表明了这条边是最外面的边。
看了解题报告,做法比较高效,一次扫描线就可以。下回再看。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define ls t<<1
#define rs t<<1|1
#define midt(tr[t].l+tr[t].r)>>1
using namespace std;
const int maxn=5011;
int x[maxn*2],y[maxn*2];
int ans;
struct no
{
    int y1,y2,x;
    int count;
    bool operator<(const no &xx) const
    {
       if(x==xx.x)
       return(count>xx.count);
       return(x<xx.x);
    }
}f[maxn*2];

struct node
{
    int x1,x2,y;
    int count;
    bool operator<(const node &xx) const
    {
       if(y==xx.y)
       return(count>xx.count);
       return(y<xx.y);
    }
}g[maxn*2];

struct
{
    int l,r;
    intlow,high,count;
    int ture;
}tr[maxn*8];

int maketree(int t,int l,int r,int d[])
{
    tr[t].l=l;
    tr[t].r=r;
    tr[t].low=d[l];
    tr[t].high=d[r];
    tr[t].ture=1;
    tr[t].count=0;
    if(l+1==r)
    return(0);
    int mid=midt;
   maketree(ls,l,mid,d);
   maketree(rs,mid,r,d);
}

int pushdown(int t)
{
   tr[ls].count=tr[t].count;
    tr[ls].ture=1;
   tr[rs].count=tr[t].count;
    tr[rs].ture=1;
}

int modify(int t,int low,int high,int txt,int d[])
{
   if(tr[t].low==low&&tr[t].high==high&&tr[t].ture==1)
    {
       tr[t].count+=txt;
       if(tr[t].count==0)
       ans+=(tr[t].high-tr[t].low)*2;
       return(0);
    }
    if(tr[t].ture)
    pushdown(t);
    tr[t].ture=0;
    int mid=midt;
   if(high<=d[mid])
   modify(ls,low,high,txt,d);
    elseif(d[mid]<=low)
   modify(rs,low,high,txt,d);
    else
    {
       modify(ls,low,d[mid],txt,d);
       modify(rs,d[mid],high,txt,d);
    }
}


int main()
{
    int n;
   while(scanf("%d",&n)!=EOF)
    {
       for(int i=1;i<=n;i++)
       {
           intx1,y1,x2,y2;
           scanf("%d%d %d%d",&x1,&y1,&x2,&y2);
          y[i]=y1;
          y[i+n]=y2;

          x[i]=x1;
          x[i+n]=x2;

          f[i].y1=y1;
          f[i].y2=y2;
          f[i].x=x1;
          f[i].count=1;

          f[i+n].y1=y1;
          f[i+n].y2=y2;
          f[i+n].x=x2;
          f[i+n].count=-1;

          g[i].x1=x1;
          g[i].x2=x2;
          g[i].y=y1;
          g[i].count=1;

          g[i+n].x1=x1;
          g[i+n].x2=x2;
          g[i+n].y=y2;
          g[i+n].count=-1;
       }

          sort(x+1,x+1+2*n);
          sort(y+1,y+1+2*n);
          sort(f+1,f+1+2*n);
          sort(g+1,g+1+2*n);

          ans=0;
          maketree(1,1,2*n,y);
           for(inti=1;i<=2*n;i++)
           {
             modify(1,f[i].y1,f[i].y2,f[i].count,y);
           }

          maketree(1,1,2*n,x);
           for(inti=1;i<=2*n;i++)
           {
             modify(1,g[i].x1,g[i].x2,g[i].count,x);
           }
          printf("%d\n",ans);

    }
    return 0;
}

原创粉丝点击