BZOJ1828 [Usaco2010 Mar]balloc 农场分配
2015-05-25 23:00
483 查看
直接贪心,我们把线段按照右端点从小到大排序,然后一个个尝试插入即可。。。
来证明贪心的正确性:
不妨设贪心得到的答案集合为$S$,最优解的答案集合为$T$
若$S$不是最优解,那么$S \not= T$,不妨设按照右端点排序后,第一个不同的位置为$i$
则$S_i \not= T_i$,分情况讨论:
(1)$S_i$的左端点在$T_i$的右端点后,由于贪心的步骤这是不可能的
(2)$S_i$的右端点在$T_i$的右端点之前:
(2.1)$S_i$的右端点在$T_i$的左端点之前,即$S_i$、$T_i$不相交,我们发现存在$S' = \{S_1, S_2, ..., S_i\} \cup \{T_i, T_{i + 1}, ..., T_n\}$,且$|S'| = |T| + 1$,矛盾
(2.2)$S_i$的右端点在$T_i$的左端点之后,即$S_i$、$T_i$相交,我们直接令$S' = T - \{T_i\} + \{S_i\}$,于是有$|S'| = |T|$,即$S'$也是最优解
故可以证明贪心的正确性
于是每次模拟的时候利用线段树即可,时间复杂度$O(mlogm + mlogn)$
View Code
来证明贪心的正确性:
不妨设贪心得到的答案集合为$S$,最优解的答案集合为$T$
若$S$不是最优解,那么$S \not= T$,不妨设按照右端点排序后,第一个不同的位置为$i$
则$S_i \not= T_i$,分情况讨论:
(1)$S_i$的左端点在$T_i$的右端点后,由于贪心的步骤这是不可能的
(2)$S_i$的右端点在$T_i$的右端点之前:
(2.1)$S_i$的右端点在$T_i$的左端点之前,即$S_i$、$T_i$不相交,我们发现存在$S' = \{S_1, S_2, ..., S_i\} \cup \{T_i, T_{i + 1}, ..., T_n\}$,且$|S'| = |T| + 1$,矛盾
(2.2)$S_i$的右端点在$T_i$的左端点之后,即$S_i$、$T_i$相交,我们直接令$S' = T - \{T_i\} + \{S_i\}$,于是有$|S'| = |T|$,即$S'$也是最优解
故可以证明贪心的正确性
于是每次模拟的时候利用线段树即可,时间复杂度$O(mlogm + mlogn)$
/************************************************************** Problem: 1828 User: rausen Language: C++ Result: Accepted Time:772 ms Memory:5708 kb ****************************************************************/ #include <cstdio> #include <algorithm> using namespace std; const int N = 1e5 + 5; const int M = 1e5 + 5; const int inf = 1e9; int read(); struct data { int l, r; inline void get() { l = read(), r = read(); } inline bool operator < (const data &d) const { return r < d.r; } } a[M]; struct seg { seg *ls, *rs; int mn, tag; #define Len (1 << 16) inline void* operator new(size_t) { static seg *mempool, *c; if (mempool == c) mempool = (c = new seg[Len]) + Len; c -> ls = c -> rs = NULL, c -> mn = c -> tag = 0; return c++; } #undef Len inline void update() { mn = min(ls -> mn, rs -> mn); } inline void push() { ls -> tag += tag, rs -> tag += tag; ls -> mn -= tag, rs -> mn -= tag; tag = 0; } #define mid (l + r >> 1) void build(int l, int r) { if (l == r) { mn = read(); return; } (ls = new()seg) -> build(l, mid), (rs = new()seg) -> build(mid + 1, r); update(); } void modify(int l, int r, int L, int R) { if (L <= l && r <= R) { ++tag, --mn; return; } push(); if (L <= mid) ls -> modify(l, mid, L, R); if (mid < R) rs -> modify(mid + 1, r, L, R); update(); } int query(int l, int r, int L, int R) { if (L <= l && r <= R) return mn; push(); int res = inf; if (L <= mid) res = min(res, ls -> query(l, mid, L, R)); if (mid < R) res = min(res, rs -> query(mid + 1, r, L, R)); update(); return res; } #undef mid } *T; int n, m, ans; int main() { int i; n = read(), m = read(); (T = new()seg) -> build(1, n); for (i = 1; i <= m; ++i) a[i].get(); sort(a + 1, a + m + 1); for (i = 1; i <= m; ++i) if (T -> query(1, n, a[i].l, a[i].r)) T -> modify(1, n, a[i].l, a[i].r), ++ans; printf("%d\n", ans); return 0; } inline int read() { static int x; static char ch; x = 0, ch = getchar(); while (ch < '0' || '9' < ch) ch = getchar(); while ('0' <= ch && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x; }
View Code
相关文章推荐
- BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树
- [BZOJ1828][Usaco2010 Mar]balloc 农场分配(贪心+线段树)
- bzoj 1828: [Usaco2010 Mar]balloc 农场分配【贪心+线段树】
- BZOJ 1828: [Usaco2010 Mar]balloc 农场分配 线段树 贪心
- BZOJ1828: [Usaco2010 Mar]balloc 农场分配
- BZOJ 1828 [Usaco2010 Mar]balloc 农场分配(贪心+线段树)
- bzoj 1828: [Usaco2010 Mar]balloc 农场分配 (贪心+线段树)
- BZOJ 1828: [Usaco2010 Mar]balloc 农场分配
- 【BZOJ】1828: [Usaco2010 Mar]balloc 农场分配(经典贪心)
- bzoj1828: [Usaco2010 Mar]balloc 农场分配 线段树+贪心
- bzoj:1828: [Usaco2010 Mar]balloc 农场分配
- 【bzoj1828/Usaco2010 Mar】balloc 农场分配——贪心+差分+优先队列
- [Usaco2010 Mar]balloc 农场分配
- [贪心][Usaco2010 Mar]balloc 农场分配
- BZOJ1828: [Usaco2010 Mar]balloc 农场分配 贪心+线段树
- BZOJ1828: [Usaco2010 Mar]balloc 农场分配
- 【bzoj1828】[Usaco2010 Mar]
- 【bzoj1828】[Usaco2010 Mar]
- BZOJ1829 : [Usaco2010 Mar]starc星际争霸
- BZOJ 1827 [Usaco2010 Mar]gather 奶牛大集会(树形DP)