《算法竞赛进阶指南》0x43线段树 扫描线算法 POJ2482

Posted randy-lo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法竞赛进阶指南》0x43线段树 扫描线算法 POJ2482相关的知识,希望对你有一定的参考价值。

题目链接:http://poj.org/problem?id=2482

给出每个点框定的区域,求区域叠加的最大值,可以通过如下算法:

将每个可行点都标记,记录这些点上的权值,维护一个叶结点是一个权值点的线段树,更新的时候注意,由于所有的点都是可行点,所以右边界要在最后删除,遇到同样的x坐标的,优先叠加左边界的权值,然后去除结束矩形的权值。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 10010;
struct node{
    int l,r;
    int ans,add;
}t[maxn<<3];
struct P{
    unsigned int x,y1,y2;
    int c;
    bool operator < (const P& a)const {
        return x<a.x || (x==a.x && c>a.c);
    }
}a[maxn<<1];
unsigned int  b[maxn<<1];
int n;
int num;
unsigned int w,h;
void build(int rt,int l,int r){
    t[rt].l=l;
    t[rt].r=r;
    t[rt].add=0;
    t[rt].ans=0;
    if(l==r)return ;
    int mid=l+r>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
}
void pushdown(int rt){
    if(t[rt].add){
        t[rt<<1].add+=t[rt].add;
        t[rt<<1|1].add+=t[rt].add;
        t[rt<<1].ans+=t[rt].add;
        t[rt<<1|1].ans+=t[rt].add;
        t[rt].add=0;
    }
    return ;
}
void update(int rt,int L,int R,int C){
    if(L<=t[rt].l && t[rt].r<=R){
        t[rt].ans+=C;
        t[rt].add+=C;
        return ;
    }
    pushdown(rt);
    int mid=(t[rt].l+t[rt].r)>>1;
    if(L<=mid)update(rt<<1,L,R,C);
    if(R>mid)update(rt<<1|1,L,R,C);
    t[rt].ans=max(t[rt<<1].ans,t[rt<<1|1].ans);
}
int get(unsigned int x){
    return lower_bound(b+1,b+num+1,x)-b;
}
void solve(){
    unsigned int x,y;
    int c;
    for(int i=1;i<=n;i++){
        int k=i<<1;
        scanf("%u%u%d",&x,&y,&c);
        a[k-1].x=x,a[k-1].y1=y,a[k-1].y2=y+h-1,a[k-1].c=c;
        a[k].x=x+w-1,a[k].y1=y,a[k].y2=y+h-1,a[k].c=-c;
        b[k-1]=y;
        b[k]=y+h-1;
    }
    sort(b+1,b+2*n+1);
    num=unique(b+1,b+2*n+1)-(b+1);
    sort(a+1,a+2*n+1);
    build(1,1,num);
    int ans=0;
    for(int i=1;i<=2*n;i++){
        int y1=get(a[i].y1);
        int y2=get(a[i].y2);
        update(1,y1,y2,a[i].c);    
        ans=max(ans,t[1].ans);//t[1]中保存了扫描段中的最大值    
    }
    cout<<ans<<endl;
}
int main(){
    while(cin>>n>>w>>h)solve();
    return 0;
}

 

以上是关于《算法竞赛进阶指南》0x43线段树 扫描线算法 POJ2482的主要内容,如果未能解决你的问题,请参考以下文章

《算法竞赛进阶指南》打卡活动 #0x00 基本算法

实验13读后感:《算法竞赛进阶指南》

算法竞赛进阶指南 走廊泼水节

《算法竞赛进阶指南》-AcWing-97. 约数之和 Sumdiv-题解

《算法竞赛进阶指南》-AcWing-97. 约数之和 Sumdiv-题解

数据结构:线段树