POJ 2482 线段树 离散化 扫描线 矩阵最大权值

题意:给出n个星星的坐标,每个星星有一个亮度,给出一个矩形的长和宽,问矩形能包括的星星的最大亮度和(不包括边框)。

思路: 平面上有若干个区域,每个区域都带有一个权值,求在那个实际上重叠的区域权值和最大。使用扫描线算法,取出每个区域的左右边界,保存2个四元组,(x,y,y+h,c) (x+w,y,y+h,-c),按照第一维的大小排序。同时关于y建立一颗线段树,维护区间最大值max1,可以认为线段树上的一个值y代表区间[y,y+1] 而区间[y,y+1+h]表示线段树中的y y+1 y+2…y+h这样线段树所维护的值便是由几个数字构成的序列了。。

逐一扫描每个四元组,在线段树中执行区间修改(可以使用延迟标记)把[y1,y2]中的每个数加c,然后用根节点更新答案

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <cmath>
using namespace std;
#define MAXN 205
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2,r,rt<<1|1
struct Line   //四元组
{
    int x,y1,y2;
    int flag;
}c[MAXN];
struct Node   //关于纵坐标y建立起一颗线段树
{
    int l,r;//线段树的左右整点 
    int max1;//max1记录最大值
    int lazy;//
    //len用来计算实在的长度,rf,lf分别是对应的左右真实的浮点数端点
}a[MAXN*3];
int cnt,numy,max1;
double y[MAXN];//记录y坐标的数组
bool cmp(Line a,Line b)//扫描线算法排序的函数
{
    if(a.x!=b.x)
      return a.x < b.x;
    else
      return a.flag<b.flag;
}
void pushup(int rt)
{
    a[rt].max1=max(a[rt<<1].max1,a[rt<<1|1].max1)+a[rt].lazy;
}
void Build(int rt,int l,int r)//构造线段树
{
    a[rt].max1=a[rt].lazy=0;
    a[rt].l=y[l];
    a[rt].r=y[r];
    if(l+1==r)  return;
    int mid=(l+r)>>1;
    Build(rt<<1,l,mid);
    Build(rt<<1|1,mid,r);//递归构造
}
void update(int L,int R,int K,int rt)//加入线段e,后更新线段树
{
    if(L<=a[rt].l&&a[rt].r<=R){
        a[rt].lazy+=K;
        a[rt].max1+=K;
        return ;
    }
    if(L<a[rt<<1].r)
        update(L,min(R,a[rt<<1].r),K,rt<<1);
    else if(a[rt<<1|1].l<R)
        update(max(a[rt<<1|1].l,L),R,K,rt<<1|1);
    pushup(rt);
}
int main()
{
    int n,w,h;
    while(scanf("%d%d%d",&n,&w,&h)==3){
        int x,y1,k,max1=-1000000;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&x,&y1,&k);
            c[cnt].x=x;
            c[cnt].y1=y1;
            c[cnt].y2=y1+h;
            c[cnt].flag=k;
            cnt++;
            c[cnt].x=x+w;
            c[cnt].y1=y1;
            c[cnt].y2=y1+h;
            c[cnt].flag=-k;
            cnt++;
            y[numy++]=y1; y[numy++]=y1+h;
        }
        cnt--; numy--;
        sort(y+1,y+numy+1); //排序
        numy=unique(y+1,y+1+numy)-(y+1); //去重
        sort(c,c+cnt,cmp);
        Build(1,numy,1);
       for(int i=0;i<cnt;i++){
        update(c[i].y1,c[i].y2,c[i].flag,1);
          max1=max(max1,a[1].max1);
       }
       printf("%d\n",max1);

    }
}

猜你喜欢

转载自blog.csdn.net/deepseazbw/article/details/81141252