poj 1151 线段树+扫描线

poj 1151 http://poj.org/problem?id=1151

大神orz

这是弱渣扫面线第一题,感觉区域赛有比较多的用的这个思想,所以赶在区域赛前熟悉一下扫描线和线段树(学习经验就是看着代码,然后一步一步测试,差不多就明白了

/**************************************************************
    Problem:poj 1151
    User: youmi
    Language: C++
    Result: Accepted
    Time:0MS
    Memory:740K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d\n",a)
#define ptlld(a) printf("%I64d\n",a)
#define rep0(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define rep_1(i,n) for(int i=n;i>=1;i--)
#define rep_0(i,n) for(int i=n-1;i>=0;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define esp 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl

using namespace std;
typedef long long ll;

int n;
const int maxn=1000;
double x[maxn];
struct node
{
    double xl,xr,y,s;
    node(){}
    node(double _xl,double _xr,double _y,double _s)
    {
        xl=_xl,xr=_xr,y=_y,s=_s;
    }
    bool operator<(const node & b)const
    {
        return y<b.y;
    }
}line[maxn];
struct Seg
{
    int l,r,flag;
    double sum;
    Seg(){}
    Seg(int _l,int _r,int _flag,double _sum)
    {
        l=_l,r=_r,flag=_flag,sum=_sum;
    }
}seg[maxn];
int sgn(double x0)
{
    if(fabs(x0)<esp)
        return 0;
    if(x0<0)
        return -1;
    else
        return 1;
}
int bs(double x0)
{
    int l=1,r=n;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(sgn(x0-x[mid])==0)
            return mid;
        if(sgn(x0-x[mid])==1)
            l=mid+1;
        else
            r=mid-1;
    }
}
void pushup(int step)
{
    if(seg[step].flag)
        seg[step].sum=x[seg[step].r+1]-x[seg[step].l];
    else if(seg[step].l==seg[step].r)
        seg[step].sum=0;
    else
        seg[step].sum=seg[lson].sum+seg[rson].sum;
}
void build(int step,int l,int r)
{
    seg[step]=Seg(l,r,0,0);
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
}
void update(int step,int l,int r,int val)
{
    if(seg[step].l==l&&seg[step].r==r)
    {
        seg[step].flag+=val;
        pushup(step);
        return;
    }
    int mid=(seg[step].l+seg[step].r)>>1;
    if(mid>=r)
        update(lson,l,r,val);
    else if(mid<l)
        update(rson,l,r,val);
    else
    {
        update(lson,l,mid,val);
        update(rson,mid+1,r,val);
    }
    pushup(step);
}
int main()
{
    //freopen("in.txt","r",stdin);
    int kase=0;
    while(~sc(n)&&n)
    {
        if(kase)
            cout<<endl;
        double x1,y1,x2,y2;
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            line[cnt++]=node(x1,x2,y1,1);
            x[cnt]=x1;
            line[cnt++]=node(x1,x2,y2,-1);
            x[cnt]=x2;
        }
        sort(x+1,x+cnt+1);
        sort(line,line+cnt);
        n=1;
        for(int i=2;i<=cnt;i++)
            if(x[i]!=x[i-1])
                x[++n]=x[i];
        build(1,1,n);
        double ans=0;
        for(int i=0;i<cnt-1;i++)
        {
            int l=bs(line[i].xl);
            int r=bs(line[i].xr)-1;
            update(1,l,r,line[i].s);
            ans+=seg[1].sum*(line[i+1].y-line[i].y);
        }
        printf("Test case #%d\n",++kase);
        printf("Total explored area: %.2f \n",ans);
    }
    return 0;
}
时间: 2024-08-06 15:58:04

poj 1151 线段树+扫描线的相关文章

poj 1151 求矩形面积并 (线段树扫描线)

题意: 给出n个矩形的左下角和右上角坐标,求这n个矩形所构成的面积 思路: 线段树扫描线 这是第一次做到线段树扫描线,刚开始也不懂 如果不懂,可以看: http://www.cnblogs.com/scau20110726/archive/2013/04/12/3016765.html 和 http://www.faceye.net/search/69289.html 我是看第一个链接弄懂的 然后学习了第二位的方法 代码上也有比较详细的注释,想可以帮到大家 code: #include<cstd

poj 3277 City Horizon (线段树 扫描线 矩形面积并)

题目链接 题意: 给一些矩形,给出长和高,其中长是用区间的形式给出的,有些区间有重叠,最后求所有矩形的面积. 分析: 给的区间的范围很大,所以需要离散化,还需要把y坐标去重,不过我试了一下不去重 也不会出错, 所有的区间都能列出来,只是在查找的时候费点事. 给的矩形相当于在同一水平线上的,也就是y1坐标相当于为0,其他的就和 poj 1151 Atlantis 差不多了. 我写的思路是按照矩形面积并的思路写的: 但是还有另一种方法也是挺简单的,就是把给的矩形按照高从小到大排序,然后依次插入线段树

POJ 3277 City Horizon(线段树+扫描线+离散化)

题目地址:POJ 3277 水题..稍微处理一下然后用求面积并的方法求即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <

线段树+扫描线求矩形面积的并

POJ 1151 Atlantis(线段树+扫描线) 参考博客https://blog.csdn.net/lwt36/article/details/48908031 上面博客的原理讲解非常清楚 在这我只对代码的模板分层讲解 一些基础的 #include <iostream> #include <cstdio> #include <string.h> #include <algorithm> #include <cmath> #define ls

【BZOJ】1382: [Baltic2001]Mars Maps (线段树+扫描线)

1382: [Baltic2001]Mars Maps Time Limit: 5 Sec  Memory Limit: 64 MB Description 给出N个矩形,N<=10000.其坐标不超过10^9.求其面积并 Input 先给出一个数字N,代表有N个矩形. 接下来N行,每行四个数,代表矩形的坐标. Output 输出面积并 Sample Input 2 10 10 20 20 15 15 25 30 Sample Output 225 本以为是傻逼题,没想到不容易啊- 线段树+扫描

BZOJ 4059 Cerc2012 Non-boring sequences 线段树+扫描线

题目大意:定义一个序列为[不无聊的]当且仅当这个序列的任意一个区间都存在一个数只出现过一次,给定一个序列,要求判断这个序列是否是[不无聊的] 定义lasti表示第i个元素上一次出现的位置(第一次出现则为0),nexti表示第i个元素下一次出现的位置(最后一次出现则为n+1),那么这个元素能成为某个区间仅出现一次的数,当且仅当这个区间的左端点在[lasti+1,i]之间,右端点在[i,nexti?1]之间 我们可以将区间的左右端点放在二维平面上,那么一个元素产生的贡献是一个矩形,我们要确定的是所有

HDU 4419 Colourful Rectangle --离散化+线段树扫描线

题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何维护每种颜色的长度着实让我伤透了脑筋.后来看了一位朋友的题解,才幡然醒悟. 开始想到了用二进制表示颜色,R用001表示,G用010表示,B用100表示.那么就可以用十进制1~7表示7种不同颜色了. 维护 cov[rt][1~3] 表示此区间内3种原色各有多少个, Len[rt][i]表示每种颜色的长

POJ 2528 (线段树+离散化) Mayor&#39;s posters

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9

poj 2777 线段树的区间更新

Count Color Time Limit: 1000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description Chosen Problem Solving and Program design as an optional course, you are required to solve al