题目大意:
有一个1维的长度为N,高度无限的水柜,现在要用N-1个挡板将其分为N个长度为1的小格,然后向水柜中注水,水可以低于挡板也可以以溢出去(这样就要与旁边格子的水位相同),现在有M次探测,探测i,y,k为查询第i个格子高度y+0.5处是否有水,k=1表示有水,k=0表示没有水,这M次探测不保证结果正确,现求结果正确个数的最大可能值。

思路:
这道题可以用类似树形dp的方法求解,依照分隔挡板由低到高的顺序将相邻的水柜合并,视为一个水柜,在合并前分别对两个水柜加水到刚好溢出,而对超出此水位的探测暂不处理,求出局部最优解(不溢出最优解f和溢出最优解g),并将各自未处理的探测合并为一个集合。不断进行此过程最后求出整个水柜的最优解。

主要操作为合并和注水,对每个水柜维护下列值:
注水高度h,不溢出最优解f,溢出最优解g,未处理探测集合E

以样例1为例说明处理方法

初状态
水柜1:h=0,f=0,g=0,E={<1,3,1>}
水柜2:h=0,f=0,g=0,E={<2,1,0>,<2,2,0>}
水柜3:h=0,f=0,g=0,E={<3,3,1>}

先将挡板由低到高排序
于是首先合并水柜1和水柜2,合并前先分别对两个水柜注水到挡板的高度3,
水柜1:h=3,f=0,g=0,E={<1,3,1>}
水柜2:h=3,f=2,g=0,E={}
合并后水柜1~2:h=3,f=2,g=0,E={<1,3,1>}

然后合并水柜1~2和水柜3,合并前先分别对两个水柜注水到挡板的高度4,
水柜1~2:h=4,f=2,g=1,E={}
水柜3:h=4,f=1,g=1,E={}
合并后水柜1~3:h=4,f=3,g=2,E={}

最后注水到最大值(比如1e9+5)
水柜1~3:h=4,f=3,g=2,E={}

于是得到结果为3

可以用并查集维护合并过程,用左斜树(或其它可合并优先队列)合并未处理的探测集合E,这样每次合并的复杂度为O(logN+logM),N次合并的总复杂度为O(NlogN+NlogM)

代码:
Problem : 5575 ( Discover Water Tank ) Judge Status : Accepted
RunId : 15797292 Language : G++ Author : qsqx
3213MS 9832K

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <map>
#include <stack>
#include <vector>
#include <memory.h>
#include <set>
#include <string.h>
#include <list>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <queue>
#define ll long long
#define forn(i,n) for(int i=0;i<n;++i)
#define rep(i,n) for(int i=1;i<=n;++i)
#define repc(i,l,r) for(int i=l;i<=r;++i)
#define mp(a,b) make_pair(a,b)
#define llf long double
#define pii pair<int,int>
using namespace std;
int l[200005];
int r[200005];
pii query[200005];//
int dist[200005];
int dsu[100005];
pii stk[200005];//
int merge(int a, int b) {if (!a)return b;else if (!b)return a;if (query[a].first > query[b].first)swap(a, b);r[a] = merge(r[a], b);if (dist[r[a]] > dist[l[a]])swap(l[a], r[a]);if (!r[a]) dist[a] = 0;else dist[a] = dist[r[a]] + 1;return a;
}
struct Node {int qu, h;int f, g;void get(int hgt) {int nw = 0;int mx = 0;int fmr = -1;int tol = 0;int nf;while (qu&&query[qu].first<hgt) {stk[tol++] = query[qu];if (query[qu].second == 0) ++nw;qu = merge(l[qu], r[qu]);}nf = nw;forn(i, tol) {if (stk[i].first != fmr) {mx = max(mx, nw);fmr = stk[i].first;}if (stk[i].second)++nw;else --nw;}mx = max(mx, nw);f = max(f+nf, g + mx);//not overflowg += nw;h = hgt;}
}nds[100005];int getgp(int u) {return dsu[u] = (dsu[u] != u ? getgp(dsu[u]) : u);
}
void mrg(int u, int v, int h) {u = getgp(u);v = getgp(v);if (nds[u].h < h) {nds[u].get(h);}if (nds[v].h < h) {nds[v].get(h);}dsu[v] = u;nds[u].qu = merge(nds[u].qu, nds[v].qu);nds[u].f += nds[v].f;nds[u].g += nds[v].g;
}
int n, m;
pii board[100005];//
void solve() {memset(l, 0, sizeof(l));memset(r, 0, sizeof(r));memset(dist, 0, sizeof(dist));memset(nds, 0, sizeof(nds));memset(board, 0, sizeof(board));memset(query, 0, sizeof(query));cin >> n >> m;rep(i, n)dsu[i] = i;rep(i, n - 1) {scanf("%d", &board[i].first);board[i].second = i;}sort(board + 1, board + n);int S = 0;rep(i, m) {int x;scanf("%d%d%d", &x, &query[i].first, &query[i].second);if (query[i].second) ++S;nds[x].qu = merge(nds[x].qu, i);}rep(i, n - 1) {mrg(board[i].second, board[i].second + 1, board[i].first);}int rt = getgp(1);nds[rt].get(1e9 + 100);cout << nds[rt].f << endl;
}
int main(){//freopen("abc.txt", "r", stdin);int T;cin >> T;rep(t, T) {printf("Case #%d: ", t);solve();}return 0;
}

HDU5575 Discover Water Tank 2015上海现场赛D题 (树形dp,并查集,左偏树)相关推荐

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

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

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

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

  3. hdu5575 Discover Water Tank

    题意: 给出个水箱,水箱两侧有无限高的隔板,水箱内有整数高度的隔板将水箱分成n-1份,现在给出m个限制,每个限制表示某个位置的某个高度有水或没水,问最多能同时满足多少个限制.n,m<=2*10^ ...

  4. 线段树合并(HDU-5575 Discover Water Tank)

    题目连接 题意: 给你一个长为n,宽为1,高为无穷的水缸.里面有n-1个高度不一的隔板隔开为1x1大小的区域.里面的水遵循物理定理.给你m次查询和回应,每个查询<x,y,z>.代表查询第x ...

  5. NYOJ 1248 海岛争霸 河南省赛真题 Floyd 或者 并查集

    海岛争霸 时间限制: 1000 ms  |  内存限制: 65535 KB 难度: 3 描述 神秘的海洋,惊险的探险之路,打捞海底宝藏,激烈的海战,海盗劫富等等.加勒比海盗,你知道吧?杰克船长驾驶着自 ...

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

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

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

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

  8. 2019ICPC上海区域赛 补题(12/13) 总结

    前言: 个人的 ICPCICPCICPC 第一站,还是值得记录一下的(虽然咕到现在才记录),总体而言体验很不错,比赛兼旅游.这套题总体印象就是树树树图,作为队里数据结构兼图论选手,这次也确实写了大部分 ...

  9. HDU 3220 Alice’s Cube (09年上海区域赛水题(位压缩、逆向搜索、打表))

    这道题是09年上海区域赛的A题,虽然很水,但是不能直接爆搜,直接爆搜要T.于是我们看到题目的要求是说当操作的步数大于3的时候就输出more,那么我们可以从终态枚举进行了三次操作所能达到的所有状态,这个 ...

最新文章

  1. mysql等价语句是_Mysql基本语句(个人笔记)
  2. HDU 1271整数对
  3. 【牛客 - 283H】图论一顿套模板(思维转化,Dijkstra)
  4. 使用C#操作Oracle Spatial的SDO_GEOMETRY对像(读取和写入)
  5. 判断当前js运行的平台环境 取自vue源码
  6. VS 2015 搭建Google Test
  7. Android 网络评分机制
  8. Linux:GCC安装与编译(详细)
  9. 【python】爬虫入门书籍推荐
  10. 深度解析:什么是支付核心?
  11. MySQL期末复习题(题库)
  12. 一文解决关于建立时间和保持时间的困惑
  13. 微信小程序 - 自定义组件中类似页面 onShow 的页面显示就触发的生命周期钩子函数(页面回退时更新数据常用, 例如回退页面更新子组件数据, 回退更新子组件中 data 内容)
  14. 如何把PDF中的一页内容替换掉
  15. 非常详尽,多图慎入:Wayland与Weston简介
  16. mysqladmin
  17. SQL基本语句使用总结
  18. php 提交按钮失效,php - 为什么td标记内的提交按钮不起作用? - SO中文参考 - www.soinside.com...
  19. 阿里云亚太市场份额第一;AWS宣布在香港推出新区域;Facebook出成绩单;微软在美国西部开建第五个大型云平台...
  20. 湖南大学与四川大学计算机,四川大学和湖南大学哪个更好一点?都是高校吗?...

热门文章

  1. 小型教育网站的开发与建设-开篇(一)
  2. GPU开发环境搭建(CUDA和 OptiX)
  3. 在网络工程师行业里,这6个误解,你知道吗
  4. 视频剪辑教程,加速小技巧,录好的所有视频增速快进
  5. 边缘计算 KubeEdge+EdgeMash
  6. VR/AR 时代就在眼前 (二)
  7. html footer写法,HTML5 footer标签元素 css3布局教程
  8. 典型DC24V接口防护电路分析
  9. VIAVI OLP-34/OLP-35/OLP-38光功率计SmartPocket
  10. 百度图片源码流出~按照颜色搜图片~提取图片主体颜色