poj 2482 Stars in Your Window(线段树+离散化+扫描线)

来源:互联网 发布:mac上能玩的热门网游 编辑:程序博客网 时间:2024/04/30 12:31
原文地址:poj 2482 Stars in Your Window(线段树+离散化+扫描线)作者:匆匆过客
题意:在一个平面内有N个星星,每个星星都在一个亮度值,用一个W*H的矩形去围这些星星,(边上的不算)求能得到的最大亮度值。

思路:想了很久一直不懂 只能看别人的解题报告 。。。。
原来只要转换一下,就能把其转换为求线段区间的最大值 每个星星所能影响的范围[(x,y),(x+w-1,y+h-1)]且有一权值它们重合就表示 能被这个矩形框在一起,也就是说,只要求出重合的矩形的权值最大就行了。

以x从小到大排序,y值离散化,投影到y轴上,那么对于每个星星的纵坐标,y,y+h-1就是每个星星可以影响到的矩形然后x,x+w-1就是一个进入事件和一个出去事件,其所带的值互为相反数. node[1].sum 保存当前的最大值当所有的矩形都遍历一遍 取其中的最大值就是ans

PS:看了讨论板说的,要用__int64 但我只把x,y,sum,add的值定义为__int64 其余为int 但 死活WA 本人认为其它的变量按题目要求是不会超过int的范围,而且也有人说 全部都用int也能过, 但在无数次WA之后,实在找不出原因,索性把全部变量都定义为__int64 就AC了 = = 。。。。我还能说什么呢,不知代码哪里写挫了。

//3008K   141MS
#include <stdio.h>
#include <algorithm>
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define Max 10010
using namespace std;
struct line
{
    __int64x,y1,y2,val;
}seg[Max*2];

struct tree
{
    intl,r;        //这两变量我觉得真的不可能超过int
    __int64sum,add;     //sum是该结点的最大亮度值,add是该区间被覆盖的值 用于延迟更新
}node[Max*8];

__int64 y[Max*2];

bool cmp (line a,line b) //x从小到大,x相等,左边的边在前 因为是x+w-1
{
    if (a.x< b.x)
       return true;
    if (a.x ==b.x&&a.val >b.val)
       return true;
    returnfalse;
}
void Build (__int64 left,__int64 right,int u)
{
    node[u].l =left;
    node[u].r =right;
    node[u].sum= node[u].add = 0;
    if (left ==right)
       return ;
    int mid =(left + right)>>1;
    Build(left,mid,L(u));
    Build(mid+1,right,R(u));
}

__int64 max (__int64 a,__int64 b)
{
    return a> b ? a : b;
}
void getdown (int u)
{
   node[L(u)].sum += node[u].add;
   node[L(u)].add += node[u].add;
   node[R(u)].sum += node[u].add;
   node[R(u)].add += node[u].add;
    node[u].add= 0;
}
void update (__int64 left,__int64 right,__int64 val,intu)    //都是常归套路,也就没什么好说
                                                                 //的了
    if (left ==y[node[u].l] && y[node[u].r] ==right)
    {
       node[u].sum += val;
       node[u].add += val;
       return ;
    }
    if(node[u].l == node[u].r)
       return ;
    if(node[u].add)
       getdown (u);
    int mid =(node[u].l + node[u].r)>>1;
    if (right<= y[mid])
       update (left,right,val,L(u));
    else if(left >= y[mid+1])
       update (left,right,val,R(u));
    else
    {
       update (left,y[mid],val,L(u));
       update (y[mid+1],right,val,R(u));
    }
    node[u].sum= max (node[L(u)].sum ,node[R(u)].sum); //父结点是儿子结点中最大的一个,而不是它
                                                       //们的和,这个应该很好理解
int main ()
{
    intn,w,h;
    while(~scanf("%d%d%d",&n,&w,&h))
    {
       for (int i = 0;i < n;i ++)
       {
           scanf ("%I64d %I64d%I64d",&seg[i].x,&seg[i].y1,&seg[i].val);
           y[i*2+1] =seg[i].y1;                             //y保存实际值 下标从1开始
           y[i*2+2] = seg[i].y1 + h - 1;
           seg[i].y2 = seg[i].y1 + h - 1;
           seg[n+i]  = seg[i] ;
           seg[n+i].x = seg[i].x + w - 1;
           seg[n+i].val =-seg[i].val;           //出边的val为负,表不在这矩形里
       }
       sort (y+1,y + 2*n + 1);
       sort (seg,seg + 2*n,cmp);

       int cnt = unique (y + 1, y + 2*n + 1) - y -1;// 离散

       Build (1,cnt,1);
       __int64 ans = 0;
       for (int i = 0;i < 2*n;i ++)
       {
           update(seg[i].y1,seg[i].y2,seg[i].val,1);
           ans = max (ans,node[1].sum);
       }
       printf ("%I64dn",ans);
    }
    return0;
}

0 0
原创粉丝点击