[BZOJ 1691] 挑剔的美食家
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=1691
[算法]
不难想到如下算法 :
将所有牛和牧草按鲜嫩程度降序排序,按顺序扫描,如果扫描到的是牧草,则将牧草的美味程度加入一个集合,否则,将答案加上比这头牛的期望价格大的牧草中价格最小的
这个贪心策略的正确性是显然的,具体实现时,我们可以维护一棵平衡树,这棵平衡树支持 : 插入/删除一个数,查询一个数的后继,我们可以方便地使用STL-set完成这个任务,为了练习平衡树,笔者使用的是伸展树
时间复杂度 : O(Nlog(N))
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 struct info { long long x,y; int opt; } a[MAXN << 1]; int i,n,m; long long ans,tmp; template <typename T> inline void read(T &x) { long long f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; } for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } struct Splay { int root,total; struct Node { int fa; long long val; int cnt; int son[2]; } Tree[MAXN << 1]; inline bool get(int x) { return Tree[Tree[x].fa].son[1] == x; } inline void rotate(int x) { int f = Tree[x].fa,g = Tree[f].fa; int tmpx = get(x),tmpf = get(f); if (!f) return; Tree[f].son[tmpx] = Tree[x].son[tmpx ^ 1]; if (Tree[x].son[tmpx ^ 1]) Tree[Tree[x].son[tmpx ^ 1]].fa = f; Tree[x].son[tmpx ^ 1] = f; Tree[f].fa = x; Tree[x].fa = g; if (g) Tree[g].son[tmpf] = x; } inline void splay(int x) { int fa; for (fa = Tree[x].fa; (fa = Tree[x].fa); rotate(x)) rotate((get(fa) == get(x)) ? fa : x); root = x; } inline int insert(long long x) { bool tmp; if (!root) { root = ++total; Tree[root].fa = 0; Tree[root].son[0] = Tree[root].son[1] = 0; Tree[root].cnt = 1; Tree[root].val = x; return total; } int now = root; while (now > 0) { if (Tree[now].val == x) { Tree[now].cnt++; splay(now); return now; } tmp = x > Tree[now].val; if (!Tree[now].son[tmp]) { Tree[now].son[tmp] = ++total; Tree[total].fa = now; Tree[total].val = x; Tree[total].cnt = 1; Tree[total].son[0] = Tree[total].son[1] = 0; splay(total); return total; } else now = Tree[now].son[tmp]; } } inline int get_pos(int x) { int now = x; while (Tree[now].son[1]) now = Tree[now].son[1]; return now; } inline void join(int x,int y) { int p = get_pos(x); splay(p); Tree[p].son[1] = y; Tree[y].fa = p; } inline void erase(int x) { Tree[x].cnt--; if (Tree[x].cnt > 0) return; if (!Tree[x].son[0] && !Tree[x].son[1]) { root = 0; return; } if (!Tree[x].son[0]) { root = Tree[x].son[1]; Tree[root].fa = 0; return; } if (!Tree[x].son[1]) { root = Tree[x].son[0]; Tree[root].fa = 0; return; } join(Tree[x].son[0],Tree[x].son[1]); } inline long long query(long long x) { int p = insert(x); int now = p; if (Tree[p].cnt > 1) { erase(p); erase(p); return x; } now = Tree[p].son[1]; while (Tree[now].son[0]) now = Tree[now].son[0]; erase(p); long long ret = Tree[now].val; splay(now); erase(now); return ret; } } T; inline bool cmp(info a,info b) { if (a.y != b.y) return a.y > b.y; else return a.opt > b.opt; } int main() { read(n); read(m); for (i = 1; i <= n; i++) { read(a[i].x); read(a[i].y); a[i].opt = 0; } for (i = 1; i <= m; i++) { read(a[n + i].x); read(a[n + i].y); a[n + i].opt = 1; } sort(a + 1,a + (n + m) + 1,cmp); for (i = 1; i <= n + m; i++) { if (a[i].opt == 0) { tmp = T.query(a[i].x); if (tmp != -1) { ans += tmp; continue; } printf("-1\n"); return 0; } else T.insert(a[i].x); } printf("%lld\n",ans); return 0; }