hdu 1828 Picture(线段树轮廓线)

Picture

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3075    Accepted Submission(s): 1616

Problem Description

A
number of rectangular posters, photographs and other pictures of the
same shape are pasted on a wall. Their sides are all vertical or
horizontal. Each rectangle can be partially or totally covered by the
others. The length of the boundary of the union of all rectangles is
called the perimeter.

Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1.

The corresponding boundary is the whole set of line segments drawn in Figure 2.

The vertices of all rectangles have integer coordinates.

Input

Your
program is to read from standard input. The first line contains the
number of rectangles pasted on the wall. In each of the subsequent
lines, one can find the integer coordinates of the lower left vertex and
the upper right vertex of each rectangle. The values of those
coordinates are given as ordered pairs consisting of an x-coordinate
followed by a y-coordinate.

0 <= number of rectangles < 5000
All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.

Please process to the end of file.

Output

Your
program is to write to standard output. The output must contain a
single line with a non-negative integer which corresponds to the
perimeter for the input rectangles.

Sample Input

7

-15 0 5 10

-5 8 20 25

15 -4 24 14

0 -6 16 4

2 15 10 22

30 10 36 20

34 0 40 16

Sample Output

228

给出 n 个矩阵 求包围这些矩阵的边界长度。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstring>
#include <map>
#include <queue>
using namespace std;
typedef pair<int,int> pii ;
typedef long long LL;
#define X first
#define Y second
#define root 1,n,1
#define lr rt<<1
#define rr rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int N = 200010;
const int M = 10000;
const int mod = 10007;
int n , m ;
struct Point { int x , y ;Point(){} };
struct Line{ int tag ; Point a, b ; }e[N];
inline bool cmp1 ( const Line &A , const Line &B ) { return A.a.x < B.a.x ; }
inline bool cmp2 ( const Line &A , const Line &B ) { return A.a.y < B.a.y ; }

int lazy[N<<2] , cnt[N<<2] , sum[N<<2] ;

void build( int l , int r , int rt ) {
    sum[rt] = lazy[rt] = cnt[rt] = 0 ;
    if( l == r ) return ;
    int mid = (l+r)>>1;
    build(lson),build(rson);
}

void Up( int l , int r , int rt ) {
    if( cnt[rt] > 0 ) sum[rt] = r - l + 1 ;
    else sum[rt] = sum[lr] + sum[rr] ;
}

void update( int l , int r , int rt , int L , int R , int tag ) {
    if( l == L && r == R ) {
        if( tag ) {
            cnt[rt]++ , lazy[rt] ++ ;
            sum[rt] = r - l + 1 ;
        }
        else {
            cnt[rt]-- , lazy[rt] -- ;
            if( cnt[rt] > 0 ) sum[rt] = r - l + 1 ;
            else {
                if( l == r ) sum[rt] = 0 ;
                else sum[rt] = sum[lr] + sum[rr] ;
            }
        }
        return ;
    }
    int mid = (l+r)>>1;
    if( L > mid ) update(rson,L,R,tag);
    else if( R <= mid ) update(lson,L,R,tag);
    else update(lson,L,mid,tag) , update(rson,mid+1,R,tag);
    Up(l,r,rt);
}

int x1[N] , x2[N] , y1[N] , y2[N];

int main()
{
    #ifdef LOCAL
       freopen("in.txt","r",stdin);
//       freopen("out.txt","w",stdout);
    #endif // LOCAL
    int _ , cas = 1 ;
    int mx , Mx , my  , My ;
    while( scanf("%d",&n) != EOF ) {
        Mx = My = -N , mx = my = N ;
        for( int i = 0 ; i < n ; ++i ) {
            scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]);
            mx = min( mx , x1[i] ); Mx = max( Mx , x2[i] );
            my = min( my , y1[i] ); My = max( My , y2[i] );
            e[i].a.x = x1[i] , e[i].a.y = y1[i]  ;
            e[i].b.x = x1[i] , e[i].b.y = y2[i] ;
            e[i].tag = 1 ;
            e[i+n].a.x = x2[i] , e[i+n].a.y = y2[i];
            e[i+n].b.x = x2[i] , e[i+n].b.y = y1[i];
            e[i+n].tag = 0 ;
        }
        int tot = n * 2 ;
        sort( e , e + tot ,cmp1 ) ;
        LL ans = 0 , last = 0 ;
        build( my , My - 1 , 1 );
        for( int i = 0 ; i < tot ; ++i ) {
            int x = e[i].a.y , y = e[i].b.y ;
            if( x > y ) swap(x,y);
            update( my , My - 1 , 1 , x , y -1 , e[i].tag );
            LL tmp = sum[1] ;
            ans += abs( tmp - last );
            last = tmp ;
        }
        for( int i = 0 ; i < n ; ++i ){
            e[i].a.x = x1[i] , e[i].a.y = y1[i]  ;
            e[i].b.x = x2[i] , e[i].b.y = y1[i] ;
            e[i].tag = 1 ;
            e[i+n].a.x = x2[i] , e[i+n].a.y = y2[i]  ;
            e[i+n].b.x = x1[i] , e[i+n].b.y = y2[i] ;
            e[i+n].tag = 0 ;
        }
        last = 0 ;
        sort( e , e + tot , cmp2 ) ;
        build(mx,Mx-1,1);
        for( int i = 0 ; i < tot ; ++i ) {
            int x = e[i].a.x , y = e[i].b.x ;
            if( x > y ) swap(x,y);
            update( mx , Mx - 1 , 1 , x , y - 1 , e[i].tag );
            LL tmp = sum[1] ;
            ans += abs( tmp - last );
            last = tmp ;
        }
        printf("%I64d\n",ans);
    }
}

时间: 2025-01-04 07:55:14

hdu 1828 Picture(线段树轮廓线)的相关文章

hdu 1828 Picture(线段树&amp;扫描线&amp;周长并)

Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2578    Accepted Submission(s): 1363 Problem Description A number of rectangular posters, photographs and other pictures of the same shap

HDU 1828 Picture 线段树+扫描线

题意:给你一些矩形的左上角点的坐标和右下角点的坐标,求周长并 最显而易见的思路就是对于x轴和y轴做两次扫描线,对于负数的坐标进行离散化.每次增加的值是线段变化量的绝对值.具体写法和求面积并的差不多. #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define lson rt << 1 , l , m

POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的,这样理论上是对的 要注意处理高度相同的线段,把底边优先处理(在代码里就是f标记为1的线段),因为若是一个矩形的底边和另一个矩形的上边重合,则这个轮廓肯定不能算 不过POJ和HDU的数据好像都比较弱,我没进行上面的细节处理也AC了,不过一个很简单的数据就会不对,所以还是要处理一下才是真正正确的代码 我

HDU 1828 Picture(矩形周长并)

HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4个方向都加完就是答案 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 5005; int n; struct Rec { int

HDU 1828 Picture(长方形的周长和)

HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4个方向都加完就是答案 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 5005; int n; struct Rec { int

hdu 1542 Atlantis(线段树&amp;扫描线&amp;面积并)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6386    Accepted Submission(s): 2814 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

hdu1828 Picture(线段树+离散化+扫描线)两种方法

C - Picture Time Limit:2000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Description A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid

HDU 1542 Atlantis(线段树扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1542 Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6788    Accepted Submission(s): 2970 Problem Description There are several ancient Greek