【转】poj 1177 pictures(2)

http://acm.pku.edu.cn/JudgeOnline/problem?id=1177

#include<iostream>
#include<algorithm>
#define MAXN 10005
using namespace std;

struct segment
{
 int L,R;
 int len,linenum,cover; 
 // 以当前区间为根的树被覆盖的区间的总长度,
 // 以当前区间为根的树被覆盖的区间数目,当前区间被覆盖的次数,
 bool lcover,rcover;
};

struct line
{
 //int start,end;//离散化之后竖边的两个Y值
 int x;
 int flag;//记录左右边
 bool operator<( const line &a )
 {
  return x<a.x;
 }
};

struct point
{
 int y;
 int num;
 bool operator<( const point & a )
 {
  return y<a.y;
 }
};

segment tree[MAXN*4];
line yline[MAXN];
point Ypoint[MAXN];
point Xpoint[MAXN];
int Xpost[MAXN][2];
int Ypost[MAXN][2];

void make_tree( int v, int l, int r )
{
 int mid;
 tree[v].L=l; tree[v].R=r;
 tree[v].linenum=tree[v].len=0;
 tree[v].lcover=tree[v].rcover=false;
 if( r-l>1 )
 {
  mid=(l+r)>>1;
  make_tree( v<<1, l, mid );
  make_tree( (v<<1)+1, mid, r );
 }
}

void getline( int v ) // 获得以当前接点为根的树被覆盖的区间总长度
{
 if( tree[v].cover>0 )tree[v].len=Ypoint[tree[v].R].y-Ypoint[tree[v].L].y;
 else if( tree[v].R-tree[v].L==1 )tree[v].len=0;
 else tree[v].len=tree[v<<1].len+tree[(v<<1)+1].len;
}

void getlinenum( int v ) //获得以当前节点为树根的子树被覆盖区间的总数
{
 if( tree[v].cover>0 )
  tree[v].lcover=tree[v].rcover=true,tree[v].linenum=1;
 else if( tree[v].R-tree[v].L==1 )
  tree[v].lcover=tree[v].rcover=false,tree[v].linenum=0;
 else  
 {
  tree[v].lcover=tree[v<<1].lcover;
  tree[v].rcover=tree[(v<<1)+1].rcover;
  tree[v].linenum=tree[v<<1].linenum+tree[(v<<1)+1].linenum-tree[v<<1].rcover*tree[(v<<1)+1].lcover;
 }
}

void update( int v, int l, int r, int flag )
{
 int mid;
 if( tree[v].L==l && tree[v].R==r )
 {
  tree[v].cover+=flag;
  getline( v );
  getlinenum( v );
  return ;
 }
 mid=(tree[v].L+tree[v].R)>>1;
 if( r<=mid )update( v<<1, l, r, flag );
 else if( l>=mid )update( (v<<1)+1, l, r, flag );
 else 
 {
  update( v<<1, l, mid, flag );
  update( (v<<1)+1, mid, r, flag );
 }
 getline( v );
 getlinenum( v );
}

int main( )
{
 int n,i,t1,t2;
 int x1,x2,y1,y2;
 while( scanf("%d",&n) != EOF )
 {
  for( i=0; i<n; i++ )
  {
   scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
   t1=i<<1;t2=(i<<1)+1;
   Xpoint[t1].y=x1;Xpoint[t2].y=x2;
   Xpoint[t1].num=-(i+1);
   Xpoint[t2].num=i+1;
   Ypoint[t1].y=y1;Ypoint[t2].y=y2;
   Ypoint[t1].num=-(i+1);  //竖边下面的点
   Ypoint[t2].num=i+1;     //竖边上面的点
   yline[t1].x=x1;yline[t2].x=x2;
   yline[t1].flag=1;//负号矩形左边
   yline[t2].flag=-1;//正号矩形右边
  }
  sort( yline, yline+(n<<1) );
  sort( Xpoint, Xpoint+(n<<1) );
  sort( Ypoint, Ypoint+(n<<1) );
  for( i=0; i<(n<<1); i++ )
  {
   if( Xpoint[i].num<0 )Xpost[-Xpoint[i].num-1][0]=i;
   else Xpost[Xpoint[i].num-1][1]=i;
  }
  for( i=0; i<(n<<1); i++ )
  {
   if( Ypoint[i].num<0 )
    Ypost[Xpost[-Ypoint[i].num-1][0]][0]=Ypost[Xpost[-Ypoint[i].num-1][1]][0]=i;
   else Ypost[Xpost[Ypoint[i].num-1][0]][1]=Ypost[Xpost[Ypoint[i].num-1][1]][1]=i;
  }
  make_tree( 1, 0, (n<<1)-1 );
  int ans=0,Len=0;
  update( 1, Ypost[0][0], Ypost[0][1], yline[0].flag );
  for( i=1; i<2*n; i++ )
  {
   ans+=2*tree[1].linenum*(yline[i].x-yline[i-1].x);
   ans+=abs(tree[1].len-Len);
   Len=tree[1].len;
   update( 1, Ypost[i][0], Ypost[i][1], yline[i].flag );
  }
  ans+=abs(tree[1].len-Len);
  printf("%d\n",ans);
 }
 return 0;
}

 
原文地址:https://www.cnblogs.com/lzhitian/p/2596629.html