Discover Water Tank HDU - 5575
题意:一个底面1*n的容器,两边无限高,中间被n-1块板阻断,给你m次观测,每次观测告诉你第i个区域是否有水,问你这些观测中最多有几个是对的。
思路:如果水超过板的高度,那么板的两边的区间就可以视为一个区间。所以只要枚举水没有溢出和水已经溢出这两种状态。我们从低到高的角度遍历板子,每次处理好这种状态,然后把这两个区间合并成一个区间,最后合并成一个区间,取一个最大值即可。我们把每个区域的观测存到一个堆中,当枚举到第i个板子时,把两边低于板高的观测取出,然后合并堆就好了。
开始不会可并堆,然后去学了一波左斜树,后来lxw告诉我__gnu_pbds有封装好的。。。
pbds版:
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>
using namespace std;
using namespace __gnu_pbds;
#define pb push_back
#define pa pair<int,int>
#define N 200005pa a[N];
int f[N];
int dp[N][2];
int finds(int x){return x==f[x]?x:f[x]=finds(f[x]); }
int get(int x,int y){int w=dp[x][1];while(!q[x].empty()){pa p=q[x].top();if(p.first>y)break;w+=p.second;dp[x][0]=max(dp[x][0],w);q[x].pop();}return w;
}
int main()
{int T,cas=1,n,m,id,h,fl;cin>>T;while(T--){scanf("%d%d",&n,&m);for(int i=1;i<n;i++){scanf("%d",&a[i].first);a[i].second=i;}for(int i=1;i<=n;i++)f[i]=i,dp[i][0]=dp[i][1]=0;sort(a+1,a+n);for(int i=1;i<=m;i++){scanf("%d %d %d",&id,&h,&fl);q[id].push(pa(h+1,fl==1?1:-1));if(!fl)dp[id][0]++,dp[id][1]++;}int ans=0,w;for(int i=1;i<n;i++){int fx=finds(a[i].second),fy=finds(a[i].second+1);dp[fy][1]=get(fx,a[i].first)+get(fy,a[i].first);dp[fy][0]=dp[fx][0]+dp[fy][0];f[fx]=fy;q[fy].join(q[fx]);}int x=finds(1);dp[x][1]=get(x,1e9+7);printf("Case #%d: %d\n",cas++,max(dp[x][0],dp[x][1]));}return 0;
}
左斜树版:
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>
using namespace std;
using namespace __gnu_pbds;
#define pb push_back
#define pa pair<int,int>
#define N 200005
__gnu_pbds::priority_queue<pa,greater<pa> >q[N];int c[N],rs[N],ls[N],dis[N],d[N],tot=0,he[N];
int New(int x,int y){c[tot]=x;d[tot]=y;ls[tot]=rs[tot]=dis[tot]=0;return tot++;
}
int Merge(int a,int b){if(!a||!b)return a+b;if(c[a]>c[b])swap(a,b);rs[a]=Merge(rs[a],b);if(dis[ls[a]]<dis[rs[a]])swap(ls[a],rs[a]);dis[a]=dis[rs[a]]+1;return a;
}
int pop(int a){return Merge(ls[a],rs[a]);}
pa a[N];
int f[N];
int dp[N][2];
int finds(int x){return x==f[x]?x:f[x]=finds(f[x]); }
int get(int x,int y){int w=dp[x][1];while(he[x]!=0){if(c[he[x]]>y)break;w+=d[he[x]];dp[x][0]=max(dp[x][0],w);he[x]=pop(he[x]);}return w;
}
int main()
{int T,cas=1,n,m,id,h,fl;cin>>T;while(T--){scanf("%d%d",&n,&m);tot=1;for(int i=1;i<n;i++){scanf("%d",&a[i].first);a[i].second=i;}for(int i=1;i<=n;i++)f[i]=i,dp[i][0]=dp[i][1]=0,he[i]=0;sort(a+1,a+n);for(int i=1;i<=m;i++){scanf("%d %d %d",&id,&h,&fl);he[id]=!he[id]?New(h+1,fl?1:-1):Merge(he[id],New(h+1,fl?1:-1));if(!fl)dp[id][0]++,dp[id][1]++;}int ans=0,w;for(int i=1;i<n;i++){int fx=finds(a[i].second),fy=finds(a[i].second+1);dp[fy][1]=get(fx,a[i].first)+get(fy,a[i].first);dp[fy][0]=dp[fx][0]+dp[fy][0];f[fx]=fy;he[fy]=Merge(he[fx],he[fy]);}int x=finds(1);dp[x][1]=get(x,1e9+7);printf("Case #%d: %d\n",cas++,max(dp[x][0],dp[x][1]));}return 0;
}
Discover Water Tank HDU - 5575相关推荐
- hdu 5575 Discover Water Tank(可合并堆)
题目链接:hdu 5575 Discover Water Tank 题意: 有一个大水箱,里面有N-1个隔板,将这个大水箱分成了N个小水箱,每个隔板有一定的高度. 现在有m条信息,每条信息表示第x个水 ...
- HDU5575 Discover Water Tank 2015上海现场赛D题 (树形dp,并查集,左偏树)
题目大意: 有一个1维的长度为N,高度无限的水柜,现在要用N-1个挡板将其分为N个长度为1的小格,然后向水柜中注水,水可以低于挡板也可以以溢出去(这样就要与旁边格子的水位相同),现在有M次探测,探测i ...
- hdu 5575 Discover Water Tank 左偏树
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5575 题意: 现在有一个巨大的水库(可视为二维的),水库中间被 n−1n-1n−1 个挡板分成了 n ...
- 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 5575 Discover Water Tank(线段树+自底向上dp+并查集)
题意 给定n个挡板和m次回答,每次回答为x号水池的H+0.5高度是否有水,问这些回答互不矛盾的最大集合. 题解 设定状态dp[i][0-1]代表第i个区间枚举到当前回答后有水的最大不矛盾集合和没水的最 ...
- HDU 5575 Discover Water Tank(左偏树)
https://vjudge.net/problem/HDU-5575 题意: 有一个水箱,被n-1块板子分成了n个部分,板子的高度不尽相同.现在有m次探测,每次探测在第x部分的y+0.5高度处是否有 ...
- HDU 5575 Discover Water Tank 并查集+左偏树
不妨假定初始答案为所有的无水询问,因为这样一定没有冲突. 然后枚举有水询问.水位线到这里时,答案能否更优. 若水位线达到某一高度,则可能淹没旁边的水箱,那么实际就变成了一个大水箱,所以考虑用并查集来优 ...
- 树形DP+并查集+左偏树, HDU-5575,Discover Water Tank,2015上海现场赛D题
只是ACM/IICPC 2015 上海区域赛的一道题.原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5575 题目描述 N-1个木板把一个水箱划分成了N ...
最新文章
- android textview参差不齐,android textView 排版显示参差不齐的解决方法
- Vlan中的 PVID vid tag untag 常识理论
- css聊天布局,CSS实现聊天布局
- Django几种缓存机制的配置和应用
- android 日历下面备注,怎样在日历的下面加备注?
- hsi转rgb公式matlab,rgb与hsi模型转换matlab程序
- (仿头条APP项目)2.主界面按钮切换Fragment页面
- KBMMW 4.6 正式版发布
- 使用R语言绘制层次聚类热图
- linux入门怎么学?
- 【java】深入了解JAVA可变长度的参数
- IntelliJ IDEA教程
- spearman相关性分析_数据的相关分析及SPSS算例
- 不入世的天才: 尼古拉·特斯拉
- 卸载CTEX后再安装LaTex时会遇到的问题
- 使用Poi-tl 生成word文档 处理word特殊符号方框带勾选 解决方法
- 绕过CDN查找真实IP方法
- 解决谷歌浏览器切后台会停止游戏
- Gunicorn-配置详解
- 结合GUI和simulink的三相电路谐波的检测与建模