BZOJ1828 [Usaco2010 Mar]balloc 农场分配

直接贪心,我们把线段按照右端点从小到大排序,然后一个个尝试插入即可。。。

来证明贪心的正确性:

不妨设贪心得到的答案集合为$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)$

  1 /**************************************************************
  2     Problem: 1828
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:772 ms
  7     Memory:5708 kb
  8 ****************************************************************/
  9
 10 #include <cstdio>
 11 #include <algorithm>
 12
 13 using namespace std;
 14 const int N = 1e5 + 5;
 15 const int M = 1e5 + 5;
 16 const int inf = 1e9;
 17
 18 int read();
 19
 20 struct data {
 21     int l, r;
 22
 23     inline void get() {
 24         l = read(), r = read();
 25     }
 26     inline bool operator < (const data &d) const {
 27         return r < d.r;
 28     }
 29 } a[M];
 30
 31 struct seg {
 32     seg *ls, *rs;
 33     int mn, tag;
 34
 35     #define Len (1 << 16)
 36     inline void* operator new(size_t) {
 37         static seg *mempool, *c;
 38         if (mempool == c)
 39             mempool = (c = new seg[Len]) + Len;
 40         c -> ls = c -> rs = NULL, c -> mn = c -> tag = 0;
 41         return c++;
 42     }
 43     #undef Len
 44
 45     inline void update() {
 46         mn = min(ls -> mn, rs -> mn);
 47     }
 48     inline void push() {
 49         ls -> tag += tag, rs -> tag += tag;
 50         ls -> mn -= tag, rs -> mn -= tag;
 51         tag = 0;
 52     }
 53
 54     #define mid (l + r >> 1)
 55     void build(int l, int r) {
 56         if (l == r) {
 57             mn = read();
 58             return;
 59         }
 60         (ls = new()seg) -> build(l, mid), (rs = new()seg) -> build(mid + 1, r);
 61         update();
 62     }
 63
 64     void modify(int l, int r, int L, int R) {
 65         if (L <= l && r <= R) {
 66             ++tag, --mn;
 67             return;
 68         }
 69         push();
 70         if (L <= mid) ls -> modify(l, mid, L, R);
 71         if (mid < R) rs -> modify(mid + 1, r, L, R);
 72         update();
 73     }
 74
 75     int query(int l, int r, int L, int R) {
 76         if (L <= l && r <= R) return mn;
 77         push();
 78         int res = inf;
 79         if (L <= mid) res = min(res, ls -> query(l, mid, L, R));
 80         if (mid < R) res = min(res, rs -> query(mid + 1, r, L, R));
 81         update();
 82         return res;
 83     }
 84     #undef mid
 85 } *T;
 86
 87 int n, m, ans;
 88
 89 int main() {
 90     int i;
 91     n = read(), m = read();
 92     (T = new()seg) -> build(1, n);
 93     for (i = 1; i <= m; ++i) a[i].get();
 94     sort(a + 1, a + m + 1);
 95     for (i = 1; i <= m; ++i)
 96         if (T -> query(1, n, a[i].l, a[i].r))
 97             T -> modify(1, n, a[i].l, a[i].r), ++ans;
 98     printf("%d\n", ans);
 99     return 0;
100 }
101
102 inline int read() {
103     static int x;
104     static char ch;
105     x = 0, ch = getchar();
106     while (ch < ‘0‘ || ‘9‘ < ch)
107         ch = getchar();
108     while (‘0‘ <= ch && ch <= ‘9‘) {
109         x = x * 10 + ch - ‘0‘;
110         ch = getchar();
111     }
112     return x;
113 }

时间: 2024-08-04 23:34:16

BZOJ1828 [Usaco2010 Mar]balloc 农场分配的相关文章

BZOJ 1828: [Usaco2010 Mar]balloc 农场分配

Description Input 第1行:两个用空格隔开的整数:N和M * 第2行到N+1行:第i+1行表示一个整数C_i * 第N+2到N+M+1行: 第i+N+1行表示2个整数 A_i和B_i Output * 第一行: 一个整数表示最多能够被满足的要求数 题解: 将请求按右端点排序,然后依次添加,用线段树判断是否能添加,不能的放弃.统计个数即可. 代码: #include<cstdio> #include<cstring> #include<algorithm>

BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树

Description Input 第1行:两个用空格隔开的整数:N和M * 第2行到N+1行:第i+1行表示一个整数C_i * 第N+2到N+M+1行: 第i+N+1行表示2个整数 A_i和B_i Output * 第一行: 一个整数表示最多能够被满足的要求数 Sample Input 5 4 1 3 2 1 3 1 3 2 5 2 3 4 5 Sample Output 3 分析:把每头牛按右端点升序排序,然后能插就插,我们需要维护一下这段区间剩余空间的最小值,如果最小值大于0说明能放进去.

【树形DP/搜索】BZOJ 1827: [Usaco2010 Mar]gather 奶牛大集会

1827: [Usaco2010 Mar]gather 奶牛大集会 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 793  Solved: 354[Submit][Status][Discuss] Description Bessie正在计划一年一度的奶牛大集会,来自全国各地的奶牛将来参加这一次集会.当然,她会选择最方便的地点来举办这次集会.每个奶牛居住在 N(1<=N<=100,000) 个农场中的一个,这些农场由N-1条道路连接,并且从任意一个

BZOJ 1827: [Usaco2010 Mar]gather 奶牛大集会( dp + dfs )

选取任意一个点为root , size[ x ] 表示以 x 为根的子树的奶牛数 , dp一次计算出size[ ] && 选 root 为集会地点的不方便程度 . 考虑集会地点由 x 点向它的子节点 son 转移 , 那么以 son 为集会地点比以 x 为集会地点要多 dist( x , son ) * ( tot - size[ x ] ) - dist( x , son ) * size[ x ] = dist( x , son ) * ( tot - 2 * size[ x ] )

【BZOJ 1827】 [Usaco2010 Mar]gather 奶牛大集会

1827: [Usaco2010 Mar]gather 奶牛大集会 Time Limit: 1 Sec  Memory Limit: 64 MB Submit: 722  Solved: 314 [Submit][Status][Discuss] Description Bessie正在计划一年一度的奶牛大集会,来自全国各地的奶牛将来参加这一次集会.当然,她会选择最方便的地点来举办这次集会.每个奶牛居住在 N(1<=N<=100,000) 个农场中的一个,这些农场由N-1条道路连接,并且从任意

BZOJ 1827: [Usaco2010 Mar]gather 奶牛大集会

Description Bessie正在计划一年一度的奶牛大集会,来自全国各地的奶牛将来参加这一次集会.当然,她会选择最方便的地点来举办这次集会.每个奶牛居住在 N(1<=N<=100,000) 个农场中的一个,这些农场由N-1条道路连接,并且从任意一个农场都能够到达另外一个农场.道路i连接农场A_i和B_i(1 <= A_i <=N; 1 <= B_i <= N),长度为L_i(1 <= L_i <= 1,000).集会可以在N个农场中的任意一个举行.另外

BZOJ1827 [Usaco2010 Mar]gather 奶牛大集会

题意:给定一棵树,求出树上的一点,使得树上的全部点到该点的距离之和最小. 思路:暴力显然是O(N^2)等死对吧. 我们首先将无根树转化为有根树,然后一边dfs求出f[i],size[i]. f[i]表示以i为根的子树中全部的点到i的距离之和,size[i]表示以i为根的子树的点数. 以下開始脑洞大开: 如今对于我们一開始的那个root,我们已经知道了答案.问题就是怎样高速的推知别的点作为根时的答案. 我们又一次进行一次dfs,当找到x时,我们用dp[fa[x]]+padis[x]*size[fa

BZOJ1829 : [Usaco2010 Mar]starc星际争霸

设出$x,y,z$三个未知量分别表示三种单位的战斗力. 那么各种不等式都可以表示成$ax+by+cz\geq 0$的形式. 注意到$z>0$,那么两边都除以$z$得到$ax+by+c\geq 0$. 然后半平面交求出所有顶点后,对于每次询问将所有顶点带入求值即可. #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int N=400; const doub

【BZOJ】1827: [Usaco2010 Mar]gather 奶牛大集会

[算法]树型DP [题解] 两遍DFS,第一次得到所有节点子树的路径和,第二次给出除了该子树外其它部分的路径和,时时计算答案. long long!!! #include<cstdio> #include<cstring> #include<algorithm> #include<cctype> #define ll long long using namespace std; const int maxn=100010; struct edge{int v