您的位置:首页 > 其它

POJ 2464 Brownie Points II(扫描线 + 两棵线段树 区间求和)

2013-02-03 20:20 501 查看
题意:

stan 划了一条竖线,ollie在这条线的基础上划一条横线,使自己能拿到的蛋糕尽可能的多。

思路:

1. 对于 y 坐标离散化,扫描线是垂直 x 轴的,从左向右:首先对 rtree 存放所有蛋糕,ltree 存放扫描线左边的蛋糕数,于是初始置 0

2. 假设离散化后 y 的点数有 m 个,代码中为了方便 query 操作,区间是 [0, m],每个线段树节点代表 y 坐标范围内的个数。

3. 因为题目中说了,x 坐标的点可能会重合,针对这种情况要特殊化考虑,多设置个 s 指针, 代码中 [s, i) 表示重合 x 坐标区间。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

#define lhs l, m, rt << 1
#define rhs m + 1, r, rt << 1 | 1

const int maxn = 200010;

typedef struct _Point {
int x, y;
bool operator < (const _Point& other)
{ return x < other.x; }
} Coord ;

class CSegTree
{
private:
int sum[maxn << 2];
public:
void pushUp(int rt)
{
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void build(int l, int r, int rt)
{
sum[rt] = 0;
if (l == r)
return ;
int m = (l + r) >> 1;
build(lhs);
build(rhs);
}
void update(int p, int value, int l, int r, int rt)
{
if (l == r)
{
sum[rt] += value;
return ;
}
int m = (l + r) >> 1;
if (p <= m)
update(p, value, lhs);
else
update(p, value, rhs);
pushUp(rt);
}
int query(int beg, int end, int l, int r, int rt)
{
if (beg <= l && r <= end)
return sum[rt];
int m = (l + r) >> 1;
int ret = 0;
if (beg <= m)
ret += query(beg, end, lhs);
if (end > m)
ret += query(beg, end, rhs);
return ret;
}
};

CSegTree ltree, rtree;
Coord cord[maxn];
int ycord[maxn];

int binSearch(int value, int arr[], int size)
{
return lower_bound(arr, arr + size, value) - arr;
}

int main()
{
int n;
while (scanf("%d", &n) && n)
{
for (int i = 0; i < n; ++i)
{
scanf("%d %d", &cord[i].x, &cord[i].y);
ycord[i+1] = cord[i].y;
}
sort(ycord + 1, ycord + n + 1);
sort(cord, cord + n);

int m = unique(ycord + 1, ycord + n + 1) - (ycord + 1);

ltree.build(0, m, 1);
rtree.build(0, m, 1);

int p;
for (int i = 0; i < n; ++i)
{
p = binSearch(cord[i].y, ycord + 1, m) + 1;
rtree.update(p, 1, 0, m, 1);
}

int best = 0;
vector<int> ret;
for (int i = 1, s = 0; i <= n; ++i)
{
if (i == n || cord[i].x != cord[i-1].x)
{
for (int j = s; j < i; ++j)
{
p = binSearch(cord[j].y, ycord + 1, m) + 1;
rtree.update(p, -1, 0, m, 1);
}

int ollie = -1, stan = -1;
for (int j = s; j < i; ++j)
{
p = binSearch(cord[j].y, ycord + 1, m) + 1;
int a = ltree.query(0, p - 1, 0, m, 1) + rtree.query(p + 1, m, 0, m, 1);
int b = rtree.query(0, p - 1, 0, m, 1) + ltree.query(p + 1, m, 0, m, 1);

if (ollie == b)
stan = min(stan, a);
else if (ollie < b)
ollie = b, stan = a;
}
if (stan == best)
ret.push_back(ollie);
else if (stan > best)
best = stan, ret.clear(), ret.push_back(ollie);

for (int j = s; j < i; ++j)
{
p = binSearch(cord[j].y, ycord + 1, m) + 1;
ltree.update(p, 1, 0, m, 1);
}

s = i;
}
}
sort(ret.begin(), ret.end());

printf("Stan: %d; Ollie:", best);

for (int i = 0; i < ret.size(); ++i)
if (i == 0 || ret[i] != ret[i-1])
printf(" %d", ret[i]);

printf(";\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: