题意:一个底面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相关推荐

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

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

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

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

  3. hdu 5575 Discover Water Tank 左偏树

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

  4. HDU 5575 Discover Water Tank

    原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5575 把每个水箱当作一个并查集,每个无水的探测当做一个左偏树.有水的探测则放在数组中.并用一个数组使水 ...

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

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

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

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

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

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

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

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

  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. android textview参差不齐,android textView 排版显示参差不齐的解决方法
  2. Vlan中的 PVID vid tag untag 常识理论
  3. css聊天布局,CSS实现聊天布局
  4. Django几种缓存机制的配置和应用
  5. android 日历下面备注,怎样在日历的下面加备注?
  6. hsi转rgb公式matlab,rgb与hsi模型转换matlab程序
  7. (仿头条APP项目)2.主界面按钮切换Fragment页面
  8. KBMMW 4.6 正式版发布
  9. 使用R语言绘制层次聚类热图
  10. linux入门怎么学?
  11. 【java】深入了解JAVA可变长度的参数
  12. IntelliJ IDEA教程
  13. spearman相关性分析_数据的相关分析及SPSS算例
  14. 不入世的天才: 尼古拉·特斯拉
  15. 卸载CTEX后再安装LaTex时会遇到的问题
  16. 使用Poi-tl 生成word文档 处理word特殊符号方框带勾选 解决方法
  17. 绕过CDN查找真实IP方法
  18. 解决谷歌浏览器切后台会停止游戏
  19. Gunicorn-配置详解
  20. 结合GUI和simulink的三相电路谐波的检测与建模

热门文章

  1. discuz 开发手机版及相关技术
  2. ecahrts柱图自动排序
  3. 游戏原画 or 游戏建模?
  4. mp4在线转换gif
  5. QT的项目组织结构和pro文件中的各关键字的含义解释
  6. C 语言编程 — 程序编译原理
  7. java 分时图_软件设计模式(观察者模式)——模拟股票价格变动并绘制分时图和K线图...
  8. 五年老Android,我决定学习后端开发了!
  9. SD存储卡被格式化,如何恢复里面的数据文件?
  10. Iphone CPU 架构类型