线段树扫描线算法

这个扫描线算法是用线段树完成的,一开始理解有点难度

http://www.cnblogs.com/scau20110726/archive/2013/04/12/3016765.html

算法的思想请看这个blog

然后最近做几个扫描线练习一下(代码还是挺难写的啊,而且变式比较难)

HDU 1542

题意:给你很多矩形,求矩形覆盖的面积
题解:这个就是模板题,理解了思想之后撸一遍模板,cnt是当前区间被覆盖了几次,len是当前区间被覆盖的长度,把x轴的坐标离散化之后,有m个点,所以对应有m-1条边,把这m-1条边对应到线段树里面建树,把m-1条边看成m-1个带权值的点

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define   MAX       10000+5
#define   MAXN      100000+5
#define   lson      l,m,rt<<1
#define   rson      m+1,r,rt<<1|1
#define   lrt       rt<<1
#define   rrt       rt<<1|1
#define   mid       int m=(r+l)>>1
#define   LL        long long
#define   ull       unsigned long long
#define   mem0(x)   memset(x,0,sizeof(x))
#define   mem1(x)   memset(x,-1,sizeof(x))
#define   meminf(x) memset(x,INF,sizeof(x))
#define   lowbit(x) (x&-x)

const int    mod   = 1000000007;
const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const int    INFF  = 1e9;
const double pi    = 3.141592653589793;
const double inf   = 1e18;
const double eps   = 1e-10;

//读入外挂
inline int read_int(){
    int ret=0;
    char tmp;
    while(!isdigit(tmp=getchar()));
    do{
        ret=(ret<<3)+(ret<<1)+tmp-'0';
    }while(isdigit(tmp=getchar()));
    return ret;
}

struct Node{
    double y,x1,x2;
    int flag;
    bool operator < (const Node &a )const {
        return y0){
            s[rt].len=x[r+1]-x[l];
        }
        else s[rt].len=s[lrt].len+s[rrt].len;
        return ;
    }
    mid;
    if(L<=m) update(L,R,val,lson);
    if(R>m) update(L,R,val,rson);
    pushup(rt,l,r);
}

int Bsearch(double k,int l,int r){
    while(l<=r){
        mid;
        if(x[m]==k) return m;
        else if(x[m]



HDU 1255

题意:给你很多矩形,计算重叠的面积

题解:看着和上面那题差不多,就是记录区间的覆盖次数,如果覆盖了两次以上,就是重叠

但是没有那么好写,要用len记录覆盖一次的长度,inlen记录覆盖两次及以上的长度

cnt是当前区间覆盖的次数,然后pushup的时候当cnt==0的时候当前区间的len和inlen都等于左右儿子的之和

cnt==1的时候当前区间的len等于区间长度,inlen等于左右儿子的len之和(因为左右儿子的len是覆盖过一次,这会大区间又被覆盖一次,所以左右儿子的len变成了大区间的inlen)

cnt>1的时候inlen等于区间长度

然后感觉并不需要pushdown,。不然看着好复杂,因为cnt只记录一层的覆盖情况,不用pushup,pushdown搞来搞去就清楚了很多

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define   MAX       10000+5
#define   MAXN      100000+5
#define   lson      l,m,rt<<1
#define   rson      m+1,r,rt<<1|1
#define   lrt       rt<<1
#define   rrt       rt<<1|1
#define   mid       int m=(r+l)>>1
#define   LL        long long
#define   ull       unsigned long long
#define   mem0(x)   memset(x,0,sizeof(x))
#define   mem1(x)   memset(x,-1,sizeof(x))
#define   meminf(x) memset(x,INF,sizeof(x))
#define   lowbit(x) (x&-x)

const int    mod   = 1000000007;
const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const int    INFF  = 1e9;
const double pi    = 3.141592653589793;
const double inf   = 1e18;
const double eps   = 1e-10;

//读入外挂
inline int read_int(){
    int ret=0;
    char tmp;
    while(!isdigit(tmp=getchar()));
    do{
        ret=(ret<<3)+(ret<<1)+tmp-'0';
    }while(isdigit(tmp=getchar()));
    return ret;
}

struct Node{
    double y,x1,x2;
    int flag;
    bool operator < (const Node &a )const {
        return y1) s[rt].inlen=x[r+1]-x[l];
    else if(s[rt].cnt==1){
        s[rt].inlen=s[lrt].len+s[rrt].len;
        s[rt].len=x[r+1]-x[l];
    }
    else{
        s[rt].inlen=s[lrt].inlen+s[rrt].inlen;
        s[rt].len=s[lrt].len+s[rrt].len;
    }
}

void build(int l,int r,int rt){
    s[rt].cnt=s[rt].len=s[rt].inlen=0;
    if(l==r) return;
    mid;
    build(lson);
    build(rson);
}

void update(int L,int R,int val,int l,int r,int rt){
    if(L<=l&&r<=R){
        s[rt].cnt+=val;
        if(s[rt].cnt>1) s[rt].inlen=x[r+1]-x[l];
        else if(s[rt].cnt==1){
            s[rt].inlen=s[lrt].len+s[rrt].len;
            s[rt].len=x[r+1]-x[l];
        }
        else{
            s[rt].inlen=s[lrt].inlen+s[rrt].inlen;
            s[rt].len=s[lrt].len+s[rrt].len;
        }
        return ;
    }
    mid;
    if(L<=m) update(L,R,val,lson);
    if(R>m) update(L,R,val,rson);
    pushup(l,r,rt);
}

int Bsearch(double k,int l,int r){
    while(l<=r){
        mid;
        if(x[m]==k) return m;
        else if(x[m]



你可能感兴趣的:(线段树扫描线算法)