您的位置:首页 > 其它

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

2016-05-19 20:39 369 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj