poj2482 Stars in Your Window(成段更新+扫描线)

来源:互联网 发布:淘宝货源外国 编辑:程序博客网 时间:2024/04/30 13:23


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

题意:给你n个星星的x,y,val,求用一个长w宽h圈住的最大亮度的值(还有这题前缀长的不忍直视啊)。


思路:这题关键点在于对问题的转化,按照最笨的暴力枚举只会超时。这里我们设刚开始给的框代号X,以ABC点为中心临时做出来的框为代号ABC...。我们知道一个矩形的中心点可以代表它的位置,那么以A为中心,作w、h的矩形A,此矩形的范围表示框X的中心点在这个范围内即可圈住该点。设想如果有两个矩形A和B有交集,那么交集部分表示既可以圈住A点,也可以圈住B点,所以任意矩形的交集表示可以圈住任意的点。那么这里求框内最大亮度就转化成了求覆盖面积的最大值。

这样的话就是成段更新求最值+扫描线的思路了。那么点如何代表矩形呢?按我们上面的思路是按照点为中心做矩形,这里直接将横坐标平移w个单位,所有点都平移效果不会变。离散纵坐标值,扫描线从左往右扫描。还要注意这里做出的矩形是有权值的,一条线段映射到线段树里就是成段更新,lazy也可以用上。


#include <stdio.h>#include <algorithm>#include <stdlib.h>#include <string.h>#include <iostream>using namespace std;typedef long long LL;const int N = 100010;const int INF = 1e8;struct line{    __int64 l, r;    __int64 sum;    __int64 add;}tree[8*N];struct node{    __int64 w, h;    __int64 val;    bool operator < (const struct node & tmp) const    {        if(w == tmp.w)            return val < tmp.val;        return w < tmp.w;    }}point[8*N];__int64 y[N*8];void build(__int64 i, __int64 l, __int64 r){    tree[i].l = l;    tree[i].r = r;    tree[i].add = 0;    tree[i].sum = 0;    if(l == r)    {        return;    }    __int64 mid = (l+r) >> 1;    build(i*2, l, mid);    build(i*2+1, mid+1, r);}__int64 binsearch(__int64 key, __int64 k){    __int64 high = k;    __int64 low = 1;    while(high >= low)    {        __int64 mid = (high+low) >> 1;        if(y[mid] == key)        {            return mid;        }        else if(y[mid] < key)        {            low = mid+1;        }        else high = mid-1;    }    return -1;}void update(__int64 i, __int64 l, __int64 r, __int64 val){    if(tree[i].l == l && tree[i].r == r)    {        tree[i].add += val;        tree[i].sum += val;        return;    }    if(tree[i].add)    {        tree[i*2].add += tree[i].add;        tree[i*2+1].add += tree[i].add;        tree[i*2].sum += tree[i].add;        tree[i*2+1].sum += tree[i].add;        tree[i].add = 0;    }    __int64 mid = (tree[i].l+tree[i].r) >> 1;    if(mid >= r)        update(i*2, l, r, val);    else if(mid < l)        update(i*2+1, l, r, val);    else    {        update(i*2, l, mid, val);        update(i*2+1, mid+1, r, val);    }    tree[i].sum = max(tree[i*2].sum, tree[i*2+1].sum);}int main(){  //  freopen("in.txt", "r", stdin);    __int64 n, w, h;    while(~scanf("%I64d%I64d%I64d", &n, &w, &h))    {        for(__int64 i = 1; i <= n; i++)        {            scanf("%I64d%I64d%I64d", &point[i].w, &point[i].h, &point[i].val);            y[i] = point[i].h;            y[i+n] = point[i].h+h;            point[i+n].w = point[i].w+w;            point[i+n].h = point[i].h;            point[i+n].val = -point[i].val;        }        sort(point+1, point+1+n*2);        sort(y+1, y+1+n*2);        __int64 k = 1;        for(__int64 i = 2; i <= n*2; i++)        {            if(y[i-1] != y[i])            {                y[++k] = y[i];            }        }        build(1, 1, k);        __int64 ans = 0;        for(__int64 i = 1; i <= n*2; i++)        {            __int64 l = binsearch(point[i].h, k);            __int64 r = binsearch(point[i].h+h, k)-1;            if(l > r) swap(l, r);          //  printf("%I64d %I64d\n", l, r);            update(1, l, r, point[i].val);            ans = max(ans, tree[1].sum);        }        printf("%I64d\n", ans);    }    return 0;}


0 0
原创粉丝点击