Stars in Your Window POJ-2482——线段树+扫描线+坐标离散化

题目链接:

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

题意:

在一个平面上给出许多星星的坐标,每个星星有一个权值。

求用长宽分别为w,h的矩形圈住的星星的权值最大为?(矩形横着放)。

思路:

一个矩形的位置可以由右上角的坐标确定下来。如果要围住一个星星,

那么这个矩形的右上角一定在以该星星为左下角长宽为w,h的矩形内。

以每个星星构造一个矩形,每个矩形有一个权值。即求一个坐标在这些矩形中权值和最大。

借助扫描线,用线段树维护单点最大值即可。线段树需用延迟标记。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=10000;

int n,w,h;

struct Point
{
    int x,y,c;
};

struct Line
{
    bool operator<(const Line &t)const{return x<t.x;}
    ll x;
    int y1,y2,c;
};

Point place[maxn];
Line line[maxn*2];
ll y[maxn*2];

int tag[maxn*2*4];
int ma[maxn*2*4];

void change(int c,int a,int b,int k,int l,int r)
{
    if(a<=l&&b>=r)
    {
        tag[k]+=c;
        ma[k]+=c;
    }
    else
    {
        int m=(l+r)>>1;
        if(a<m)change(c,a,b,2*k+1,l,m);
        if(b>m)change(c,a,b,2*k+2,m,r);
        ma[k]=max(ma[2*k+1],ma[2*k+2])+tag[k];
    }
}

int main()
{
    while(~scanf("%d%d%d",&n,&w,&h))
    {
        int cy=0;
        for(int i=0;i<n;++i)
        {
            scanf("%d%d%d",&place[i].x,&place[i].y,&place[i].c);
            y[cy++]=place[i].y;
            y[cy++]=(ll)place[i].y+h-1;
        }
        sort(y,y+cy);
        cy=unique(y,y+cy)-y;

        int cl=0;
        for(int i=0;i<n;++i)
        {
            line[cl].x=place[i].x;
            line[cl].c=place[i].c;
            line[cl].y1=lower_bound(y,y+cy,(ll)place[i].y)-y;
            line[cl++].y2=lower_bound(y,y+cy,(ll)place[i].y+h-1)-y;

            line[cl]=line[cl-1];
            line[cl].x+=w;
            line[cl].c=-line[cl].c;
            ++cl;
        }

        memset(tag,0,sizeof(tag));
        memset(ma,0,sizeof(ma));

        sort(line,line+cl);
        int ans=0;

        for(int i=0;i<cl;++i)
        {
            change(line[i].c,line[i].y1,line[i].y2+1,0,0,cy+1);
            ans=max(ans,ma[0]);
        }

        printf("%d\n",ans);
    }

    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/judp/p/10872838.html