HDU-5575-Discover Water Tank
2017-11-21 22:17
323 查看
ACM模版
初始默认所有 z=0 的情况,然后枚举 z=1 的情况来更新答案,并且可以用并查集来维护合并的水箱,既然水箱要合并,那么计算水箱的合并用可并堆比较快,可并堆中比较常用编码难度比较低的数到左偏树了。
这里由于需要向左向右进行查找挡板,合并后就忽视掉中间的挡板从而视作一个整体,所以仿真链式存储结构比较好。
描述
题解
左偏树可解。初始默认所有 z=0 的情况,然后枚举 z=1 的情况来更新答案,并且可以用并查集来维护合并的水箱,既然水箱要合并,那么计算水箱的合并用可并堆比较快,可并堆中比较常用编码难度比较低的数到左偏树了。
这里由于需要向左向右进行查找挡板,合并后就忽视掉中间的挡板从而视作一个整体,所以仿真链式存储结构比较好。
代码
#include <iostream> #include <algorithm> #include <cstring> #include <vector> using namespace std; typedef pair<int, int> pii; const int MAXN = 1e5 + 10; const int MAXM = 2e5 + 5; int n, m, x, y, z, ans; int L[MAXN], R[MAXN], LH[MAXN], RH[MAXN], O[MAXN], X[MAXN]; vector<pii> vp; // 左偏树相关 int tot, v[MAXM], l[MAXM], r[MAXM], d[MAXM], Heap[MAXN]; // 合并左偏树 int merge(int x, int y) { if (x == 0) { return y; } if (y == 0) { return x; } if (v[x] > v[y]) { swap(x, y); } r[x] = merge(r[x], y); if (d[l[x]] < d[r[x]]) { swap(l[x], r[x]); } d[x] = d[r[x]] + 1; return x; } // 初始化可并堆结点 inline int init(int x) { v[++tot] = x; l[tot] = r[tot] = d[tot] = 0; return tot; } // 左偏树的插入操作 inline int insert(int x, int y) { return merge(x, init(y)); } // 取得左偏树中的最小值 inline int top(int x) { return v[x]; } // 弹出左偏树 inline int pop(int x) { return merge(l[x], r[x]); } // 判断左偏树是否非空 inline bool empty(int x) { return x == 0; } // 初始化可并堆 void initHeap() { memset(Heap, 0, sizeof(Heap)); tot = 0; } // 并查集相关 int p[MAXN]; // 初始化并查集 void initSet() { for (int i = 1; i <= n; i++) { p[i] = i; } } // 查找集合的祖先 int find(int x) { return x == p[x] ? x : p[x] = find(p[x]); } // 合并集合 inline void Union(int x, int y) { x = find(x); y = find(y); if (x == y) { return ; } p[y] = x; if (x < y) { RH[x] = RH[y]; L[R[x]] = x; R[x] = R[y]; } else { LH[x] = LH[y]; R[L[x]] = x; L[x] = L[y]; } // 合并可并堆 Heap[x] = merge(Heap[x], Heap[y]); X[x] += X[y]; O[x] += O[y]; } int main() { int T; scanf("%d", &T); for (int ce = 1; ce <= T; ce++) { scanf("%d%d", &n, &m); LH[1] = RH = INT_MAX; L = n - 1; for (int i = 1; i < n; i++) { scanf("%d", &RH[i]); // 用于快速查询水箱的左右挡板 LH[i + 1] = RH[i]; // 用于快速查询左右方水箱 L[i] = i - 1; R[i] = i + 1; } initHeap(); vp.clear(); ans = 0; while (m--) { scanf("%d%d%d", &x, &y, &z); if (z == 1) { vp.push_back(pii(y + 1, x)); } else { Heap[x] = Heap[x] ? insert(Heap[x], y) : init(y); ans++; } } initSet(); sort(vp.begin(), vp.end()); for (int i = 1; i <= n; i++) { O[i] = X[i] = 0; } for (int i = 0; i < vp.size(); i++) { x = find(vp[i].second); y = vp[i].first; // 向左溢出 while (y > LH[x]) { Union(x, L[x]); x = find(x); } // 向右溢出 while (y > RH[x]) { Union(x, R[x]); x = find(x); } // 删除水位以下的X while (!empty(Heap[x]) && top(Heap[x]) < y) { Heap[x] = pop(Heap[x]); X[x]++; } // 更新答案 if (++O[x] >= X[x]) { ans += (O[x] - X[x]); O[x] = X[x] = 0; } } printf("Case #%d: %d\n", ce, ans); } return 0; }
相关文章推荐
- hdu 5575 Discover Water Tank(可合并堆)
- HDU 5575 Discover Water Tank(并查集+左偏树/启发式合并)
- HDU 5575 Discover Water Tank(左偏树)
- HDU 5575 Discover Water Tank 并查集+左偏树
- HDU 5575 Discover Water Tank
- 树形DP+并查集+左偏树, HDU-5575,Discover Water Tank,2015上海现场赛D题
- HDU5575 Discover Water Tank 2015上海现场赛D题 (树形dp,并查集,左偏树)
- 2015 上海区域赛 D Discover water tank 并查集dp+左偏树
- hdu5575 Discover Water Tank
- hdu 4183 Pahom on Water 最大流 isap
- hdu 4445 Crazy Tank(物理过程枚举)
- hdu 2516 取石子游戏(water)
- HDU5443——The Water Problem(2015年长春区域赛)
- hdu 5443 The Water Problem(长春网络赛——暴力)
- hdu 4445 Crazy Tank (暴力枚举)
- hdu 5443 The Water Problem
- HDU 5443 The Water Problem RMQ
- HDU 5443 The Water Problem [rmq]
- HDU 5443 The Water Problem(水题 找区间最大值)——2015 ACM/ICPC Asia Regional Changchun Online
- ACM学习历程—HDU 5443 The Water Problem(RMQ)(2015长春网赛1007题)