您的位置:首页 > 其它

POJ 2482 Stars in Your Window 线段树+扫描线

2016-03-17 19:43 288 查看
妈个鸡,要不是队友提醒,我能把题面上的那封情书读完,读了一半多了都

然后题意就是,在一个平面直角坐标系上,有一些点,每个点有一个权值,用一个矩形框去框住他们,问怎么才能使框住的所有点的权值和最大,边界上的点不算。

边界上的点 不算,我之前只做到过一次边界上的点算的啊,怎么办,把长和宽都各自-1就好啦。处理之后,设长为w,宽为h。

大概就是,把一个点沿一个方向,假如说是x轴,沿x轴向正方向延长w个长度,然后这是一条入边,在y+h+1上,建一条相应的出边,就是权值取个负数,就相当于把这条边又给删去啦。

然后将所有的边按y排序,根据y从小到大,加入边,就是更新(x,x+w)这个区间。想想,这样的话,某一点 x0就可以有x0为右边界的矩形的框住的权值和,然后y又是从下往上扫的,而且还有出边,所以(x0,y0)表示以这个点为右上角的矩形框住的权值和。

比如我们更新到了y=yi,在把所有y=yi的边都更新之后,线段树存的是x,对应的最大值。所以线段树的根的最大值,就代表在y=yi下(xi,yi)为右上角的矩形框住最大权值和。

然后y从0扫到最大值,就可以得到最大权值和啦。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 10002
#define uint unsigned int
uint x_data[maxn * 2], y_data[maxn * 2];
struct Node
{
unsigned int x, y;
int val;
void made(unsigned int a, unsigned int b,int c)
{
x = a, y = b, val = c;
}
}node[maxn];
struct edge_mode
{
int y, l, r, val;
void edge_make(int y, int l, int r, int val)
{
this->y = y;
this->l = l;
this->r = r;
this->val = val;
}
}edge[20005];
struct segment
{
int add, max;
}segtree[160005];
bool cmp(edge_mode a, edge_mode b)
{
if (a.y < b.y) return true;
else return false;
}
void init(int id, int l, int r)
{
segtree[id].add = segtree[id].max = 0;
if (l == r) return;
init(id << 1, l, (l + r) >> 1);
init(id << 1 | 1, ((l + r) >> 1) + 1, r);
}
void update(int id, int l, int r, int nl, int nr, int val)
{
if (r<nl || l>nr) return;
if (l >= nl&&r <= nr)
{
segtree[id].add += val;
segtree[id].max += val;
return;
}
update(id << 1, l, (l + r) >> 1, nl, nr, val);
update(id << 1 | 1, ((l + r) >> 1) + 1, r, nl, nr, val);
segtree[id].max = max(segtree[id << 1].max, segtree[id << 1 | 1].max) + segtree[id].add;
}
int main()
{
//freopen("input.txt", "r", stdin);
int n, w, h;
while ((scanf("%d%d%d", &n, &w, &h)) == 3)
{
--w, --h;
init(1, 0, 20000);
//unsigned int x, y;
for (int i = 0; i < n; ++i)
{
scanf("%u%u%d", &node[i].x, &node[i].y, &node[i].val);
x_data[2 * i] = node[i].x, x_data[2 * i + 1] = node[i].x + w;
y_data[2 * i] = node[i].y, y_data[2 * i + 1] = node[i].y + h + 1;
}
sort(x_data, x_data + 2 * n);
sort(y_data, y_data + 2 * n);
uint x_d = unique(x_data, x_data + 2 * n) - x_data, y_d = unique(y_data, y_data + 2 * n) - y_data;
for (int i = 0; i < n; ++i)
{
int x1 = lower_bound(x_data, x_data + x_d, node[i].x) - x_data;
int y1 = lower_bound(y_data, y_data + y_d, node[i].y) - y_data;
int x2 = lower_bound(x_data, x_data + x_d, node[i].x + w) - x_data;
int y2 = lower_bound(y_data, y_data + y_d, node[i].y + h + 1) - y_data;
edge[2 * i].edge_make(y1, x1, x2, node[i].val);
edge[2 * i + 1].edge_make(y2, x1, x2, -1 * node[i].val);
//printf("%d %d %d %d %d\n", x1, y1, x2, y2, node[i].val);
}
sort(edge, edge + 2 * n, cmp);
int ans = 0;
for (int i = 0, t = 0; i <= 20000; i++)
{
while (edge[t].y == i&&t < 2 * n)
{
update(1, 0, 20000, edge[t].l, edge[t].r, edge[t].val);
t++;
}
//if (i <= 5)
//printf("%d\n", segtree[1].max);
ans = max(ans, segtree[1].max);
}
printf("%d\n", ans);
}
//while (1);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: