HDU 5575 Discover Water Tank(左偏树)
https://vjudge.net/problem/HDU-5575
题意:
有一个水箱,被n-1块板子分成了n个部分,板子的高度不尽相同。现在有m次探测,每次探测在第x部分的y+0.5高度处是否有水,回答0代表没水,1代表有水。现在要求出这m次探测最多有多少次是正确的。
思路:
挺难的一道题目吧。
一开始如果把水箱当成空的,那么所有的无水探测就都是真的,至于有水探测的话,接下来我们可以一点一点的加水,这就要求将有水探测排序。每个部分可能会有多个无水探测(比如在第1部分,它进高度为1、3、5的地方都进行无水探测),那么在被淹没的时候肯定最先淹没高度为1的地方。这样的话,对于每个部分都可以建立一个优先队列,每次弹出值最小的。但是这些部分还会因为淹没而变成一部分,这时候要将两个部分的优先队列合并起来,这样的话,就是一个左偏树了。
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 8 typedef pair<int,int> pll; 9 const int INF = 0x3f3f3f3f; 10 const int maxn = 1e5 + 5; 11 12 int n,m,ans,tot; 13 int LH[maxn],RH[maxn],L[maxn],R[maxn]; 14 int heap[maxn]; 15 int ok[maxn],nok[maxn],p[maxn]; 16 17 vector<pll> query; 18 19 struct node 20 { 21 int l,r,dis,key; 22 }t[2*maxn]; 23 24 int initHeap(int x) 25 { 26 t[++tot].key = x; 27 t[tot].l = t[tot].r = t[tot].dis = 0; 28 return tot; 29 } 30 31 int merge(int x, int y) 32 { 33 if(x == 0) return y; 34 if(y == 0) return x; 35 if(t[x].key>t[y].key) swap(x,y); 36 t[x].r = merge(t[x].r,y); 37 if(t[t[x].l].dis < t[t[x].r].dis) swap(t[x].l,t[x].r); 38 if(t[x].r==0) t[x].dis = 0; 39 else t[x].dis = t[t[x].r].dis + 1; 40 return x; 41 } 42 43 int insert(int x, int y) 44 { 45 return merge(x,initHeap(y)); 46 } 47 48 int pop(int x) 49 { 50 return merge(t[x].l,t[x].r); 51 } 52 53 int finds(int x) 54 { 55 return x==p[x]?x:p[x]=finds(p[x]); 56 } 57 58 void unions(int x, int y) 59 { 60 x = finds(x); 61 y = finds(y); 62 if(x==y) return; 63 64 p[y] = x; 65 if(x>y) //合并两个部分 66 { 67 LH[x] = LH[y]; 68 L[x] = L[y]; 69 } 70 else 71 { 72 RH[x] = RH[y]; 73 R[x] = R[y]; 74 } 75 76 heap[x] = merge(heap[x],heap[y]); //合并两个部分的左偏树 77 ok[x] += ok[y]; 78 nok[x] += nok[y]; 79 } 80 81 int main() 82 { 83 //freopen("in.txt","r",stdin); 84 int T; 85 scanf("%d",&T); 86 int kase = 0; 87 while(T--) 88 { 89 query.clear(); 90 memset(heap,0,sizeof(heap)); 91 92 scanf("%d%d",&n,&m); 93 LH[1] = RH[n] = INF; 94 for(int i=1;i<n;i++) 95 { 96 scanf("%d",&RH[i]); 97 LH[i+1] = RH[i]; 98 L[i] = i-1; //i的左边 99 R[i] = i+1; //i的右边 100 } 101 L[n]=n-1; 102 ans = tot = 0; 103 while(m--) 104 { 105 int x,y,z; 106 scanf("%d%d%d",&x,&y,&z); 107 if(z==0) 108 { 109 if(heap[x]==0) heap[x] = initHeap(y); 110 else heap[x] = insert(heap[x],y); 111 ans++; 112 } 113 else 114 { 115 query.push_back(make_pair(y,x)); 116 } 117 } 118 sort(query.begin(),query.end()); 119 for(int i=1;i<=n;i++) ok[i]=nok[i]=0; 120 for(int i=1;i<=n;i++) p[i] = i; 121 for(int i=0;i<query.size();i++) 122 { 123 int x = finds(query[i].second); 124 int y = query[i].first; 125 while(y>LH[x]) unions(x,L[x]); //向左溢出 126 while(y>RH[x]) unions(x,R[x]); //向右溢出 127 while(heap[x]!=0 && t[heap[x]].key<y) 128 { 129 heap[x] = pop(heap[x]); 130 nok[x]++; 131 } 132 ok[x]++; //当前进行的是真 133 if(ok[x]>=nok[x]) 134 { 135 ans+=ok[x]-nok[x]; 136 ok[x] = nok[x] = 0; 137 } 138 } 139 printf("Case #%d: %d\n",++kase,ans); 140 } 141 return 0; 142 }
转载于:https://www.cnblogs.com/zyb993963526/p/7849543.html
HDU 5575 Discover Water Tank(左偏树)相关推荐
- hdu 5575 Discover Water Tank 左偏树
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5575 题意: 现在有一个巨大的水库(可视为二维的),水库中间被 n−1n-1n−1 个挡板分成了 n ...
- HDU 5575 Discover Water Tank(线段树+自底向上dp+并查集)
题意 给定n个挡板和m次回答,每次回答为x号水池的H+0.5高度是否有水,问这些回答互不矛盾的最大集合. 题解 设定状态dp[i][0-1]代表第i个区间枚举到当前回答后有水的最大不矛盾集合和没水的最 ...
- hdu 5575 Discover Water Tank(可合并堆)
题目链接:hdu 5575 Discover Water Tank 题意: 有一个大水箱,里面有N-1个隔板,将这个大水箱分成了N个小水箱,每个隔板有一定的高度. 现在有m条信息,每条信息表示第x个水 ...
- HDU 5575 Discover Water Tank 并查集+左偏树
不妨假定初始答案为所有的无水询问,因为这样一定没有冲突. 然后枚举有水询问.水位线到这里时,答案能否更优. 若水位线达到某一高度,则可能淹没旁边的水箱,那么实际就变成了一个大水箱,所以考虑用并查集来优 ...
- HDU 5575 Discover Water Tank
原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5575 把每个水箱当作一个并查集,每个无水的探测当做一个左偏树.有水的探测则放在数组中.并用一个数组使水 ...
- HDU 5575 Discover Water Tank 并查集 树形DP
题意: 有一个水槽,边界的两块板是无穷高的,中间有n-1块隔板(有高度),现有一些条件(i,y,k),表示从左到右数的第i列中,在高度为(y+0.5)的地方是否有水(有水:k = 1),问最多能同时满 ...
- HDU 1512 Monkey King(左偏树+并查集)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1512 题 意: 有n个猴子,一开始每个猴子只认识自己.每个猴子有一个力量值,力量值越大表示 ...
- HDU5575 Discover Water Tank 2015上海现场赛D题 (树形dp,并查集,左偏树)
题目大意: 有一个1维的长度为N,高度无限的水柜,现在要用N-1个挡板将其分为N个长度为1的小格,然后向水柜中注水,水可以低于挡板也可以以溢出去(这样就要与旁边格子的水位相同),现在有M次探测,探测i ...
- 树形DP+并查集+左偏树, HDU-5575,Discover Water Tank,2015上海现场赛D题
只是ACM/IICPC 2015 上海区域赛的一道题.原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5575 题目描述 N-1个木板把一个水箱划分成了N ...
最新文章
- maven install 报错 source 1.5 中不支持 lambda 表达式
- cocos2d-x初探学习笔记(16)--LayerColor
- 异形3×3魔方还原教程_【理论篇】三阶魔方4.33千亿亿种变化是怎么计算出来的?...
- JEECG - 基于代码生成器的J2EE智能开发框架 续四: 查询条件SQL生成器设计思路
- 玩了10小时赛博朋克2077,我觉得很失望
- python之元组操作
- 【长文】CNN调优总结
- UG NX11.0 软件安装教程
- weka与mysql相连_Weka与MySQL连接配置
- Maven的setting仓库配置
- 证明:二阶导函数大于零时为凹函数
- Python+OpenCV对证件照换底
- 阿里云账号实名认证解决方案
- 库存转换是什么意思_什么是库存?
- 数组排序(O(n的二次方))
- 【数值分析/计算方法】插值法及其余项MATLAB仿真实验
- 双系统安装 小记 历时9小时 过关斩将! Ubuntu19.10 + RUFUS 经验之谈
- 计算机专业,刚上大一,该如何学习?
- 徐进的信念:IE工业工程与精益生产管理的区别
- 文献解读|植物对低温胁迫的反应:低温胁迫改变了大白菜的抗氧化代谢能力