原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5575

把每个水箱当作一个并查集,每个无水的探测当做一个左偏树。有水的探测则放在数组中。并用一个数组使水箱和左偏树对应起来(一个水箱最多对应一个左偏树,即使一个水箱有多个无水的探测,我们也可以通过左偏树的合并使它们变为一个)。
首先,假设所有水箱无水,那么所有结果为无水的探测的数量一定是一个解,把这个解记为ans(当然此时并不知道这是不是最优解)。接着开始更新答案,大体的操作是,按水位高低从小到大枚举有水探测,在同一个水箱的同一个高度下,有水与无水的探测是互相矛盾的,当遇到某个水箱的某个水位下的有水探测多于无水探测,我们就可以更新答案了,就是让ans+=两个探测的差值。当有水小于等于无水时,我们可以不做操作(反正你操作了也只能使答案变小,偏离我们求最优解的目标),之后再更新到这里的时候我们再检查一遍。
之后就可以输出答案~\(≧▽≦)/~啦啦啦

怎么可能……自己觉得,一些具体操作还是很复杂的,恩恩,讲一下具体操作。
不过建议读者在看之前,先自己想一想,而且本文章的标题就有提示了。

水箱的合并,这一步可以将主要部分的代码时间复杂度从接近O(mn)降到O(m+n),在枚举有水探测时,需要确认这个高度的水位会不会溢出,覆盖到其它水箱,影响到这些水箱里的无水探测,这样太慢了。此时左偏树和并查集就来了,因为是从高到低枚举水位的,所以当某水箱的水位发生了溢出时,这几个水箱在之后都可以看做一个水箱。所以我们不断合并水箱,n次合并以后,最终所有水箱变成了一个大水箱(其实我们不一定会进行到这一步,一切取决于有水探测最高的水位)。水箱的合并,一个是并查集合并,让几个水箱变为一个水箱,同时也有这些水箱里无水探测的合并。(多说几句,有水探测是按水位从低到高进行的嘛,所以我们看看这个水箱里的水位最低的无水探测在不在这个高度范围内就好)(又是合并又是优先队列,这个就是左偏树的优势)
关于水箱的合并,需要记录水箱的左右闸的高度,才可以确认水是否会溢出,因此合并时左右闸的合并需要注意一下。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef pair<int,int> mp;
const int INF=0x3f3f3f3f;
const int MAXN=1e5+5;
const int MAXM=MAXN<<1;
int LH[MAXN],RH[MAXN],L[MAXN],R[MAXN],O[MAXN],X[MAXN];
vector<mp> vec;int heap[MAXN],l[MAXM],r[MAXM],h[MAXM],v[MAXM],f[MAXN];
int tot;
int find(int x){ return f[x]==x?x:f[x]=find(f[x]); }
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(h[l[x]]<h[r[x]]) swap(l[x],r[x]);h[x]=h[r[x]]+1;return x;
}
void Union(int x,int y){x=find(x);y=find(y);if(x==y) return ;f[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 pop(int x){return merge(l[x],r[x]);
}int main(){int T,kase=0;scanf("%d",&T);while(T--){int n,m,ans=0;scanf("%d%d",&n,&m);LH[1]=RH[n]=INF;L[n]=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;}vec.clear();memset(heap,0,sizeof(heap));tot=0;while(m--){int x,y,z;scanf("%d%d%d",&x,&y,&z);if(z){vec.push_back(mp(y+1,x));}else{++ans;v[++tot]=y;l[tot]=r[tot]=h[tot]=0;heap[x]=heap[x]?merge(heap[x],tot):tot;}}for(int i=1;i<=n;++i) f[i]=i;sort(vec.begin(),vec.end());for(int i=1;i<=n;++i) O[i]=X[i]=0;for(int i=0;i<vec.size();++i){int x=find(vec[i].second);int y=vec[i].first;while(y>LH[x]){Union(x,L[x]);x=find(x);}while(y>RH[x]){Union(x,R[x]);x=find(x);}while(heap[x]!=0&&v[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",++kase,ans);}
}

HDU 5575 Discover Water Tank相关推荐

  1. hdu 5575 Discover Water Tank(可合并堆)

    题目链接:hdu 5575 Discover Water Tank 题意: 有一个大水箱,里面有N-1个隔板,将这个大水箱分成了N个小水箱,每个隔板有一定的高度. 现在有m条信息,每条信息表示第x个水 ...

  2. hdu 5575 Discover Water Tank 左偏树

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5575 题意: 现在有一个巨大的水库(可视为二维的),水库中间被 n−1n-1n−1 个挡板分成了 n ...

  3. HDU 5575 Discover Water Tank 并查集 树形DP

    题意: 有一个水槽,边界的两块板是无穷高的,中间有n-1块隔板(有高度),现有一些条件(i,y,k),表示从左到右数的第i列中,在高度为(y+0.5)的地方是否有水(有水:k = 1),问最多能同时满 ...

  4. HDU 5575 Discover Water Tank(线段树+自底向上dp+并查集)

    题意 给定n个挡板和m次回答,每次回答为x号水池的H+0.5高度是否有水,问这些回答互不矛盾的最大集合. 题解 设定状态dp[i][0-1]代表第i个区间枚举到当前回答后有水的最大不矛盾集合和没水的最 ...

  5. HDU 5575 Discover Water Tank(左偏树)

    https://vjudge.net/problem/HDU-5575 题意: 有一个水箱,被n-1块板子分成了n个部分,板子的高度不尽相同.现在有m次探测,每次探测在第x部分的y+0.5高度处是否有 ...

  6. HDU 5575 Discover Water Tank 并查集+左偏树

    不妨假定初始答案为所有的无水询问,因为这样一定没有冲突. 然后枚举有水询问.水位线到这里时,答案能否更优. 若水位线达到某一高度,则可能淹没旁边的水箱,那么实际就变成了一个大水箱,所以考虑用并查集来优 ...

  7. HDU5575 Discover Water Tank 2015上海现场赛D题 (树形dp,并查集,左偏树)

    题目大意: 有一个1维的长度为N,高度无限的水柜,现在要用N-1个挡板将其分为N个长度为1的小格,然后向水柜中注水,水可以低于挡板也可以以溢出去(这样就要与旁边格子的水位相同),现在有M次探测,探测i ...

  8. Discover Water Tank HDU - 5575

    题意:一个底面1*n的容器,两边无限高,中间被n-1块板阻断,给你m次观测,每次观测告诉你第i个区域是否有水,问你这些观测中最多有几个是对的. 思路:如果水超过板的高度,那么板的两边的区间就可以视为一 ...

  9. 树形DP+并查集+左偏树, HDU-5575,Discover Water Tank,2015上海现场赛D题

    只是ACM/IICPC 2015 上海区域赛的一道题.原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5575 题目描述 N-1个木板把一个水箱划分成了N ...

最新文章

  1. Objectice-C之类层次结构
  2. [html] 如何禁止html页面缓存?
  3. ELK套件FileBeat部署
  4. IIS解决 上传文件大小限制
  5. 如果把Python代码写成这样子就太难看了
  6. python能以文本和二进制方式处理文件_使用Python进行二进制文件读写的简单方法(推荐)...
  7. 【开发随笔】以强化学习环境 gym 库为例:为什么日常中我应该试图标准化接口?
  8. php 验证码功能的实现原理,php验证码实现原理
  9. 重磅!!Redis 6.0.0 已发布,有史以来改变最大的版本
  10. linux等 入门思维导图
  11. [Jsoi2010]连通数
  12. Hibernate与mybatis比较
  13. 自动点击王-全能自动点击王软件
  14. MSN:常见故障“步步通”(转)
  15. matlab方程组函数画图,MATLAB学习1 之画图函数
  16. DynamipsGUI使用方法
  17. oracle 序列号连号,火并VariPrint技术指标(HaiyaaVariPrint.PDF
  18. PyQt4-入门学习(1)
  19. NetCore mysql Connection open error . The given key ‘25971‘ was not present in the dictionary
  20. 采用MCaaS模式 SAP为有孚网络提供基于HANA的解决方案及服务

热门文章

  1. 【labview】基于Labview的齿轮传动测控系统设计与研究
  2. 搭建网站?(手把手教你)
  3. 从卖产品到建电站 我国光伏企业海外战略升级
  4. 机器学习算法基础(6): 信息论,决策树和随机森林
  5. 使用Photoshop为产品标记尺寸参数
  6. 【JavaScript 逆向】知乎 jsvmp,x-zse-96 参数 3.0 分析
  7. C语言程序设计作业02
  8. 细述!!DHCP中继服务配置!!
  9. 【浙江名度控股】企业在APP和小程序之间如何抉择?
  10. Gerrit version 2.12.9 is now available