POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告

题意:

求矩形周长和。

思路:

左扫上扫,扫过了。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
struct Seg {
    int lx,rx,ly,ry,h,v;
    friend bool operator < (Seg a,Seg b)
    {
        return a.h<b.h;
    }
} seg1[11000],seg2[11000];
int _hx[21000],_hy[21000],sum[500000],lz[500000];
void push_up1(int rt,int l,int r)
{
    if(lz[rt]) {
        sum[rt]=_hx[r+1]-_hx[l];
    } else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update1(int rt,int l,int r,int ql,int qr,int v)
{
    if(ql>r||qr<l)return ;
    if(ql<=l&&r<=qr) {
        lz[rt]+=v;
        push_up1(rt,l,r);
        return ;
    }
    int mid=(l+r)>>1;
    update1(rt<<1,l,mid,ql,qr,v);
    update1(rt<<1|1,mid+1,r,ql,qr,v);
    push_up1(rt,l,r);
}
void push_up2(int rt,int l,int r)
{
    if(lz[rt]) {
        sum[rt]=_hy[r+1]-_hy[l];
    } else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update2(int rt,int l,int r,int ql,int qr,int v)
{
    if(ql>r||qr<l)return ;
    if(ql<=l&&r<=qr) {
        lz[rt]+=v;
        push_up2(rt,l,r);
        return ;
    }
    int mid=(l+r)>>1;
    update2(rt<<1,l,mid,ql,qr,v);
    update2(rt<<1|1,mid+1,r,ql,qr,v);
    push_up2(rt,l,r);
}
int main()
{
    int lx,rx,ly,ry,n,i,j;
    scanf("%d",&n);
    for(i=0; i<n; i++) {
        scanf("%d%d%d%d",&lx,&ly,&rx,&ry);
        _hx[i]=lx,_hx[i+n]=rx,_hy[i]=ly,_hy[i+n]=ry;

        seg1[i].lx=lx,seg1[i].rx=rx,seg1[i].v=1,seg1[i].h=ly;
        seg1[i+n].lx=lx,seg1[i+n].rx=rx,seg1[i+n].v=-1,seg1[i+n].h=ry;

        seg2[i].ly=ly,seg2[i].ry=ry,seg2[i].v=1,seg2[i].h=lx;
        seg2[i+n].ly=ly,seg2[i+n].ry=ry,seg2[i+n].v=-1,seg2[i+n].h=rx;
    }
    sort(_hx,_hx+n*2);
    sort(_hy,_hy+n*2);
    sort(seg1,seg1+n*2);
    sort(seg2,seg2+n*2);
    int m1=unique(_hx,_hx+n*2)-_hx;
    int m2=unique(_hy,_hy+n*2)-_hy;
    int ans=0,ql,qr;
    memset(sum,0,sizeof(sum));
    memset(lz,0,sizeof(lz));
    for(i=0; i<n*2; i++) {
        ql=lower_bound(_hx,_hx+m1,seg1[i].lx)-_hx;
        qr=lower_bound(_hx,_hx+m1,seg1[i].rx)-_hx-1;
        int t=sum[1];
        update1(1,0,m1-1,ql,qr,seg1[i].v);
        ans+=abs(sum[1]-t);
    }
    memset(sum,0,sizeof(sum));
    memset(lz,0,sizeof(lz));
    for(i=0; i<n*2; i++) {
        ql=lower_bound(_hy,_hy+m2,seg2[i].ly)-_hy;
        qr=lower_bound(_hy,_hy+m2,seg2[i].ry)-_hy-1;
        int t=sum[1];
        update2(1,0,m2-1,ql,qr,seg2[i].v);
        ans+=abs(sum[1]-t);
    }
    printf("%d\n",ans);
    return 0;
}

Picture

Time Limit: 2000MS   Memory Limit: 10000K
Total Submissions: 10332   Accepted: 5485

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.

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

Source

IOI 1998

POJ训练计划1177_Picture(扫描线/线段树+离散),布布扣,bubuko.com

时间: 2024-10-29 10:46:22

POJ训练计划1177_Picture(扫描线/线段树+离散)的相关文章

hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> #include <algorithm> #define MAXN 110 #define LL ((rt<<1)+1) #define RR ((rt<<1)+2) using namespace std; int n; struct segment{ double l

POJ训练计划2777_Count Color(线段树/成段更新/区间染色)

解题报告 题意: 对线段染色,询问线段区间的颜色种数. 思路: 本来直接在线段树上染色,lz标记颜色.每次查询的话访问线段树,求出颜色种数.结果超时了,最坏的情况下,染色可以染到叶子节点. 换成存下区间的颜色种数,这样每次查询就不用找到叶子节点了,用按位或来处理颜色种数. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace

POJ训练计划2828_Buy Tickets(线段树/单点更新)

解题报告 题意: 插队完的顺序. 思路: 倒着处理数据,第i个人占据第j=pos[i]+1个的空位. 线段树维护区间空位信息. #include <iostream> #include <cstdio> #include <cstring> using namespace std; struct node { int x,v; } num[201000]; int sum[1000000],ans[201000]; void cbtree(int rt,int l,in

POJ 1151 Atlantis 扫描线+线段树

点击打开链接 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17252   Accepted: 6567 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of pa

HDU1542_Atlantis(扫描线/线段树+离散)

解题报告 题目传送门 题意: 求矩形并面积. 思路: 离散+线段树+扫描线. #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Seg { int v; double h,lx,rx; friend bool operator < (Seg a,Seg b) { return a.h<b

HDU1255_覆盖的面积(扫描线/线段树+离散)

解题报告 题目传送门 题意: 求面积交. 思路: 不会呀. 只知道线段树应该维护覆盖数大于2的线段长度. 不会更新,看了别人写的理解的,太菜了. 用sum1和sum2分别来表示覆盖数为1的区间长度和覆盖数为2的区间长度. 更新时即要更新sum1也要更新sum2: 区间如果被覆盖 sum1为实际区间长度,如果覆盖一次,sum2为左右子树的sum1和,覆盖两次就为实际区间长度. 没有被覆盖就直接等于左右子树的和. #include <algorithm> #include <iostream

ZOJ1659_Mobile Phone Coverage(扫描线/线段树+离散)

解题报告 题目传送门 题意: 求矩形面积并 思路: 扫描线+线段树.要离散化,坐标是浮点型的. 对于线段树(区间)与点坐标对应起来可以这样 区间[1,4]对应的线段树. #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Seg { int v; double lx,rx,h; friend bool

Picture POJ - 1177(扫描线 + 线段树)

题意:求矩形并的面积.. 解析: 扫描线第一道题....自下而上扫描的... 如果不懂什么是扫描线戳我 #include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <q

POJ 1151 Atlantis(线段树 + 扫描线)

转载请注明原文:http://www.cnblogs.com/burning-flame/p/5934653.html 题目链接:http://poj.org/problem?id=1151 题意: 给你 n 个矩形的对角线坐标,求 n 个矩形并集的面积. 做法: 扫描线 + 线段树. 因为作线段树的题遇到了扫描线,只是粗浅的了解了一下. 就像字面上的:线性扫描一遍,对于每个单元,因为某些事件的发生会有一些变化. 举个例子: 现有长度为 n 的数组a,同时有 n 个区间覆盖[li, ri],对于