https://vjudge.net/problem/HDU-5575

题意:

有一个水箱,被n-1块板子分成了n个部分,板子的高度不尽相同。现在有m次探测,每次探测在第x部分的y+0.5高度处是否有水,回答0代表没水,1代表有水。现在要求出这m次探测最多有多少次是正确的。

思路:

挺难的一道题目吧。

一开始如果把水箱当成空的,那么所有的无水探测就都是真的,至于有水探测的话,接下来我们可以一点一点的加水,这就要求将有水探测排序。每个部分可能会有多个无水探测(比如在第1部分,它进高度为1、3、5的地方都进行无水探测),那么在被淹没的时候肯定最先淹没高度为1的地方。这样的话,对于每个部分都可以建立一个优先队列,每次弹出值最小的。但是这些部分还会因为淹没而变成一部分,这时候要将两个部分的优先队列合并起来,这样的话,就是一个左偏树了。

 #include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std; typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + ; int n,m,ans,tot;
int LH[maxn],RH[maxn],L[maxn],R[maxn];
int heap[maxn];
int ok[maxn],nok[maxn],p[maxn]; vector<pll> query; struct node
{
int l,r,dis,key;
}t[*maxn]; int initHeap(int x)
{
t[++tot].key = x;
t[tot].l = t[tot].r = t[tot].dis = ;
return tot;
} int merge(int x, int y)
{
if(x == ) return y;
if(y == ) return x;
if(t[x].key>t[y].key) swap(x,y);
t[x].r = merge(t[x].r,y);
if(t[t[x].l].dis < t[t[x].r].dis) swap(t[x].l,t[x].r);
if(t[x].r==) t[x].dis = ;
else t[x].dis = t[t[x].r].dis + ;
return x;
} int insert(int x, int y)
{
return merge(x,initHeap(y));
} int pop(int x)
{
return merge(t[x].l,t[x].r);
} int finds(int x)
{
return x==p[x]?x:p[x]=finds(p[x]);
} void unions(int x, int y)
{
x = finds(x);
y = finds(y);
if(x==y) return; p[y] = x;
if(x>y) //合并两个部分
{
LH[x] = LH[y];
L[x] = L[y];
}
else
{
RH[x] = RH[y];
R[x] = R[y];
} heap[x] = merge(heap[x],heap[y]); //合并两个部分的左偏树
ok[x] += ok[y];
nok[x] += nok[y];
} int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
int kase = ;
while(T--)
{
query.clear();
memset(heap,,sizeof(heap)); scanf("%d%d",&n,&m);
LH[] = RH[n] = INF;
for(int i=;i<n;i++)
{
scanf("%d",&RH[i]);
LH[i+] = RH[i];
L[i] = i-; //i的左边
R[i] = i+; //i的右边
}
L[n]=n-;
ans = tot = ;
while(m--)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(z==)
{
if(heap[x]==) heap[x] = initHeap(y);
else heap[x] = insert(heap[x],y);
ans++;
}
else
{
query.push_back(make_pair(y,x));
}
}
sort(query.begin(),query.end());
for(int i=;i<=n;i++) ok[i]=nok[i]=;
for(int i=;i<=n;i++) p[i] = i;
for(int i=;i<query.size();i++)
{
int x = finds(query[i].second);
int y = query[i].first;
while(y>LH[x]) unions(x,L[x]); //向左溢出
while(y>RH[x]) unions(x,R[x]); //向右溢出
while(heap[x]!= && t[heap[x]].key<y)
{
heap[x] = pop(heap[x]);
nok[x]++;
}
ok[x]++; //当前进行的是真
if(ok[x]>=nok[x])
{
ans+=ok[x]-nok[x];
ok[x] = nok[x] = ;
}
}
printf("Case #%d: %d\n",++kase,ans);
}
return ;
}

HDU 5575 Discover Water Tank(左偏树)的更多相关文章

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

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

  2. HDU 1512 Monkey King(左偏树+并查集)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1512 [题目大意] 现在有 一群互不认识的猴子,每个猴子有一个能力值,每次选择两个猴子,挑出他们所 ...

  3. HDU 5818 Joint Stacks(左偏树)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5818 [题目大意] 给出两个栈A B(初始时为空),有三种操作: push.pop.merge. ...

  4. HDU 1512 Monkey King(左偏树模板题)

    http://acm.hdu.edu.cn/showproblem.php?pid=1512 题意: 有n只猴子,每只猴子一开始有个力量值,并且互相不认识,现有每次有两只猴子要决斗,如果认识,就不打了 ...

  5. HDU 1512 Monkey King(左偏树)

    Description Once in a forest, there lived N aggressive monkeys. At the beginning, they each does thi ...

  6. hdu 1512 Monkey King 左偏树

    题目链接:HDU - 1512 Once in a forest, there lived N aggressive monkeys. At the beginning, they each does ...

  7. hdu 1512 Monkey King —— 左偏树

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1512 很简单的左偏树: 但突然对 rt 的关系感到混乱,改了半天才弄对: 注意是多组数据! #includ ...

  8. HDU 1512 Monkey King (左偏树+并查集)

    题意:在一个森林里住着N(N<=10000)只猴子.在一开始,他们是互不认识的.但是随着时间的推移,猴子们少不了争斗,但那只会发生在互不认识 (认识具有传递性)的两只猴子之间.争斗时,两只猴子都 ...

  9. HDU 1512 左偏树+并查集

    思路: 左偏树里面掺了一些并查集的应用 这里放一份左偏树的代码模板 重点就是merge函数了-- int merge(int k1,int k2){ if(!k1||!k2)return k1+k2; ...

随机推荐

  1. 【javascript】获取 格式化时间

    function getDate() { var myDate = new Date(); var month = myDate.getMonth() + 1; var day = myDate.ge ...

  2. Linux基础命令---显示路由表route

    route route指令用于显示或者修改IP路由表.它的主要用途是在使用ifconfig(8)程序配置接口后,通过接口设置到特定主机或网络的静态路由.当使用add或del选项时,路由将修改路由表.如 ...

  3. C#获取驱动器盘符

    一.使用ManagementObjectSearcher类 static void Main(string[] args) { SelectQuery selectQuery = new Select ...

  4. GUI界面相应事件

    function varargout = GUI19(varargin) % GUI19 MATLAB code for GUI19.fig % GUI19, by itself, creates a ...

  5. web前端学习路线(含20个真实web开发项目集合)

    目前web前端工程师日均岗位缺口已经超过50000,随着互联网+的深入发展,html5作为前端展示技术,市场人才需求量将呈直线上涨. Web前端工程师的岗位职责是利用HTML.CSS.Java.DOM ...

  6. kubernetes install for centos

    官方的文档写的很清楚 https://kubernetes.io/docs/getting-started-guides/centos/centos_manual_config/ 如果已经安装过doc ...

  7. Java 高级开发必修知识---内部类

    摘自:http://www.cnblogs.com/lsy131479/p/8798912.html Java 内部类分为: 1)成员内部类 2)静态嵌套类 3)方法内部类 4)匿名内部类 内部类的共 ...

  8. Prometheus监控学习笔记之Prometheus监控简介

    0x00 Prometheus容器监控解决方案 Prometheus(普罗米修斯)是一个开源系统监控和警报工具,最初是在SoundCloud建立的.它是一个独立的开放源码项目,并且独立于任何公司.不同 ...

  9. flask模板,路由,消息提示,异常处理

    1.flask的路由与反向路由 from flask import Flask, request, url_for app = Flask(__name__) @app.route('/') def ...

  10. windows下vc编译和debug nginx

    总体来说,各个步骤以及版本参考官方文档http://nginx.org/en/docs/howto_build_on_win32.html一点没错,有些细节没说清楚. To build nginx: ...