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 坐标区间。
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; }
相关文章推荐
- poj 2464 Brownie Points II(两棵线段树——线段树区间和)
- Brownie Points II - POJ 2464 线段树
- poj 2464 Brownie Points II(扫描线)
- 线段树专题:poj 2464 Brownie Points II
- POJ 2464 Brownie Points II(线段树:扫描线)
- poj 2464 Brownie Points II (扫描线)
- POJ 2464 Brownie Points II(树状数组||线段树)
- poj 2464 Brownie Points II 树状数组
- hdu 1156 && poj 2464 Brownie Points II (BIT)
- POJ 2464 Brownie Points II(树状数组+扫描线)
- POJ 2464 Brownie Points II 树状数组+扫描线
- POJ 2464 Brownie Points II --树状数组
- Poj 2464 Brownie Points II(平面两条垂直的先划分成四个象限,一三象限和二四象限各有多少个)
- POJ 2464 Brownie Points II(树状数组)
- poj 2464 Brownie Points II
- POJ 2464 Brownie Points II --树状数组
- Poj 3416 Crossing + Poj 2464 Brownie Points II (树状数组)
- POJ 2464 Brownie Points II
- POJ 2464 Brownie Points II(树状数组)
- POJ - 1177 Picture(线段树 扫描线 区间合并)