HDU 5575 Discover Water Tank 并查集+左偏树
2016-08-10 15:10
295 查看
不妨假定初始答案为所有的无水询问,因为这样一定没有冲突。
然后枚举有水询问、水位线到这里时,答案能否更优。
若水位线达到某一高度,则可能淹没旁边的水箱,那么实际就变成了一个大水箱,所以考虑用并查集来优化,为保证合并顺序正确,先对有水询问按水位高度排序。
下面思考更新答案,朴素的做法是枚举此水位线下的有水询问和无水询问的差,但实际上因为有水询问的水位高度已经排序,我们会做大量重复枚举,所以考虑排序后来做,但是因为有合并操作,所以考虑用左偏树来维护无水询问。
时间复杂度O(α(n) + mlogm)
然后枚举有水询问、水位线到这里时,答案能否更优。
若水位线达到某一高度,则可能淹没旁边的水箱,那么实际就变成了一个大水箱,所以考虑用并查集来优化,为保证合并顺序正确,先对有水询问按水位高度排序。
下面思考更新答案,朴素的做法是枚举此水位线下的有水询问和无水询问的差,但实际上因为有水询问的水位高度已经排序,我们会做大量重复枚举,所以考虑排序后来做,但是因为有合并操作,所以考虑用左偏树来维护无水询问。
时间复杂度O(α(n) + mlogm)
#include <bits/stdc++.h> using namespace std; #define N 100010 #define INF INT_MAX int n,m,l_b ,r_b ,l_t ,r_t ,x ,o ; int tot,v[N*2],l[N*2],r[N*2],d[N*2],heap[N*2]; struct node { int x,y; bool operator<(const node&b) const { return y == b.y ? x < b.x : y < b.y; } }q[N*2]; int cnt,ans; int fa ; int merge(int x,int y) { if(!x) return y; if(!y) 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) { tot++; 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]); } int getfa(int x) { if(x == fa[x]) return x; fa[x] = getfa(fa[x]); return fa[x]; } void mergeSet(int _x,int _y) { _x = getfa(_x); _y = getfa(_y); if(_x == _y) return; fa[_x] = _y; if(_x < _y) { l_b[_y] = l_b[_x]; r_t[l_t[_x]] = _y; l_t[_y] = l_t[_x]; } else { r_b[_y] = r_b[_x]; l_t[r_t[_x]] = _y; r_t[_y] = r_t[_x]; } heap[_y] = merge(heap[_x],heap[_y]); x[_y] += x[_x]; o[_y] += o[_x]; } int main() { int t; cin >> t; for(int ii = 1; ii <= t; ii++) { ans = cnt = tot = 0; cin >> n >> m; memset(heap,0,sizeof(heap)); memset(o,0,sizeof(o)); memset(x,0,sizeof(x)); int _x,_y,_z,_h; l_b[1] = INF; r_b = INF; l_t = n-1; for(int i = 1 ; i < n; i++) { scanf("%d",&_x); l_b[i+1] = r_b[i] = _x;<span style="white-space:pre"> </span>//合并时需要的信息 l_t[i] = i - 1; r_t[i] = i + 1; } for(int i = 0; i < m; i++) { scanf("%d%d%d",&_x,&_y,&_z); if(_z == 0) { ans++; heap[_x] = heap[_x] ? insert(heap[_x],_y) : init(_y); } else { cnt++; q[cnt].x = _x; q[cnt].y = _y + 1; } } for(int i = 1; i <= n; i++) fa[i] = i; sort(q+1,q+1+cnt); for(int i = 1; i <= cnt; i++) { _h = q[i].y; _x = q[i].x; _x = getfa(_x); while(_h > l_b[_x]) { mergeSet(l_t[_x],_x); _x = getfa(_x); } while(_h > r_b[_x]) { mergeSet(r_t[_x],_x); _x = getfa(_x); } while(heap[_x] && top(heap[_x]) < _h) { //x,o数组统计无水 有水询问的和 heap[_x] = pop(heap[_x]); x[_x]++; } o[_x]++; if(o[_x] >= x[_x]) { ans += (o[_x] - x[_x]); o[_x] = x[_x] = 0; } } printf("Case #%d: %d\n",ii,ans); } return 0; }
相关文章推荐
- 树形DP+并查集+左偏树, HDU-5575,Discover Water Tank,2015上海现场赛D题
- HDU 5575 Discover Water Tank(左偏树)
- HDU-5575-Discover Water Tank
- HDU 5575 Discover Water Tank(并查集+左偏树/启发式合并)
- 2015 上海区域赛 D Discover water tank 并查集dp+左偏树
- HDU 5575 Discover Water Tank
- hdu 5575 Discover Water Tank(可合并堆)
- HDU5575 Discover Water Tank 2015上海现场赛D题 (树形dp,并查集,左偏树)
- HDU 1512 Monkey King 并查集+左偏树
- HDU 1512 (左偏树 并查集)
- hdu 1512 Monkey King (左偏树可并堆 并查集)
- HDU 1512 Monkey King 左偏树 + 并查集
- hdu1512 & zoj2334Monkey King(左偏树 + 并查集)
- hdu1512 & zoj2334Monkey King(左偏树 + 并查集)
- hdu-1512 Monkey King [并查集+左偏树]
- HDU1512 Monkey King【并查集+左偏树】
- HDU 1512 浅谈可并堆即左偏树模板及并查集灵活应用
- hdu5575 Discover Water Tank
- hdu1512 & zoj2334Monkey King(左偏树 + 并查集)
- HDU 1213 How Many Tables(并查集)