HDU 5575 Discover Water Tank 并查集+左偏树
来源:互联网 发布:c语言点滴pdf百度云 编辑:程序博客网 时间:2024/05/16 00:52
不妨假定初始答案为所有的无水询问,因为这样一定没有冲突。
然后枚举有水询问、水位线到这里时,答案能否更优。
若水位线达到某一高度,则可能淹没旁边的水箱,那么实际就变成了一个大水箱,所以考虑用并查集来优化,为保证合并顺序正确,先对有水询问按水位高度排序。
下面思考更新答案,朴素的做法是枚举此水位线下的有水询问和无水询问的差,但实际上因为有水询问的水位高度已经排序,我们会做大量重复枚举,所以考虑排序后来做,但是因为有合并操作,所以考虑用左偏树来维护无水询问。
时间复杂度O(α(n) + mlogm)
#include <bits/stdc++.h>using namespace std;#define N 100010#define INF INT_MAXint n,m,l_b[N],r_b[N],l_t[N],r_t[N],x[N],o[N];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[N];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[n] = INF; l_t[n] = 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;}
0 0
- HDU 5575 Discover Water Tank 并查集+左偏树
- HDU 5575 Discover Water Tank(并查集+左偏树/启发式合并)
- 树形DP+并查集+左偏树, HDU-5575,Discover Water Tank,2015上海现场赛D题
- HDU 5575 Discover Water Tank
- HDU-5575-Discover Water Tank
- 2015 上海区域赛 D Discover water tank 并查集dp+左偏树
- HDU5575Discover Water Tank 2015上海现场赛D题 (树形dp,并查集,左偏树)
- [Shanghai2015]Discover Water Tank解题报告
- hdu5443The Water Problem 并查集
- HDU 1512 (左偏树 并查集)
- HDU 1512 左偏树+并查集
- HDU 3371 并查集
- HDU 2473 并查集
- hdu 1116 并查集
- HDU 1856 并查集
- HDU 1598 并查集
- HDU-1232 并查集
- 【并查集】hdu 2818
- Hdu 5812 Distance(三种操作. 1.插入x 2.删除x 3.在集合中找到一个数y,使得y->x,每次能除以一个素数或者乘上一个素数,问最少的操作次数)
- LA3635 Pie (二分判定)
- java多态特性
- spring mvc对静态资源的处理
- 新的软件架构: Synergistic Software Architecture
- HDU 5575 Discover Water Tank 并查集+左偏树
- 文件上传
- IO多路复用 epoll
- ComputeScreenPos 详解
- JavaEE程序猿之吃的是草挤出的是奶(12)
- 数据库隔离级别详解
- in_array()
- QT定时器的一些注意
- ab 工具安装