题目描述

给出一个长度为 n 宽度为 1 ,高度无限的水箱,有 n−1  个挡板将其分为 n 个 1 - 1 的小格,然后向每个小格中注水,水如果超过挡板就会溢出到挡板的另一边,这里的水是满足物理定律的(在无挡板阻拦的情况下会向低处流),现在有 m  个条件 (i,y,k) ,表示从左到右数的第 i 个格子中,在高度为 y+0.5  的地方是否有水,k=1 表示有水,k=0 表示没有水,请求出这 m 个条件最多能同时满足多少个条件。本题有多组数据。

输入格式

第一行一个正整数 T ,为数据组数。
第二行两个正整数 n 、m ,中间用空格隔开。
接下来一行 n−1 个整数,表示从左到右每一块隔板的高度。
接下来 m 行,每行三个整数 i 、y 、k ,表示一个条件。

输出格式

共 T 行,每行对应一组数据的答案。

样例

样例输入

2
3 4
3 4
1 3 1
2 1 0
2 2 0
3 3 1
2 2
2
1 2 0
1 2 1

样例输出

3
1

数据范围与提示

对于 20% 的数据,n,m≤16;
对于另外 10% 的数据,只存在指明某处有水的条件;
对于另外 30% 的数据,n,m≤1000;
对于 100% 的数据,n,m≤1e5,T≤5;

看到这道题,首先应该想到最高的隔板把整个区间分割成两个独立的部分,所以对于整段的答案,可以是左右两个部分的独立的答案(即水没有淹没最高的那个隔板),或者先把两个部分淹没,让水没过最高的隔板,然后在两侧最近的更高的隔板(箱壁可视为无限高的隔板)的高度以下讨论答案。

我用的是线段树维护区间最高挡板位置,用可并堆维护区间所有要求。

初始时,对于每一个单位水槽,把它上方所有要求按高度维护小根堆,合并时就先直接合并它左右两个部分,再将堆中左右小于两侧隔板高度的要求按照顺序提出来,枚举淹没高度,用前缀有水条件个数加后缀无水条件个数更新答案,设这个答案最大值为sum。

对于区间[L,R],若L=R,ans(L,R)=sum。

否则,[L,R]一定能从最高的隔板处分为[L,k],[k+1,R],两个部分,

可以用ans(L,k)+ans(k+1,R)+高于第k和第k+1之间的隔板低于L外侧隔板且低于R外侧隔板间所有无水条件的个数更新答案,

也可以用所有[L,R]之间低于第k和第k+1之间的隔板的有水条件个数+sum更新答案。

是的有点像分治...

复杂度分析的话,每个隔板可以和左侧比它高的第一个隔板和右侧比它高的第一个隔板分别形成两个区间,所以大概有2n个区间吧...然后每个要求在可并堆中共计被访问一次,删除一次,所以再加一个mlogm,肯定是能过的。

AC代码如下:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define M 200020
#define mid (l+r>>1)
using namespace std;
int read(){
int nm=0,fh=1;char cw=getchar();
for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
return nm*fh;
}
struct req{int pos,hs,tpe;}p[M];
bool cmp(req i,req j){
if(i.pos==j.pos) return i.hs<j.hs;
return i.pos<j.pos;
}
int n,m,T,tmp,L[M],R[M],c[M<<2],t[M],ans,rt[M<<2],f[M<<2];
int tot[M<<2],dst[M<<2],son[M][2],fs[M],gt[M],pre[M],suf[M],tk;
void build(int x,int l,int r){
if(l==r){c[x]=l;return;}
build(x<<1,l,mid),build(x<<1|1,mid+1,r);
if(t[c[x<<1]]>t[c[x<<1|1]]) c[x]=c[x<<1];
else c[x]=c[x<<1|1];
}
int top(int x,int l,int r,int lt,int rt){
if(rt<l||r<lt) return lt;
if(lt<=l&&r<=rt) return c[x];
int t1=top(x<<1,l,mid,lt,rt),t2=top(x<<1|1,mid+1,r,lt,rt);
return t[t1]>t[t2]?t1:t2;
}
int merge(int x,int y){
if(x*y==0) return x+y;
if(p[x].hs>p[y].hs) return merge(y,x);
int t1=son[x][0],t2=son[x][1],k=merge(t2,y);
son[x][1]=k;
if(dst[k]>dst[t1]) swap(k,t1);
dst[x]=dst[k]+1,son[x][0]=t1,son[x][1]=k;
return x;
}
int del(int x){
int t1=son[x][0],t2=son[x][1];
son[x][0]=son[x][1]=dst[x]=0;
return merge(t1,t2);
}
void dp(int &x,int l,int r){
x=++tmp,f[x]=tot[x]=0;
int cnt=0,rf=min(t[l-1],t[r]),sum=0;
if(l==r) rt[x]=fs[l];
else{
int tp=top(1,1,n-1,l,r-1);
dp(L[x],l,tp),dp(R[x],tp+1,r);
rt[x]=merge(rt[L[x]],rt[R[x]]);
tot[x]=tot[L[x]]+tot[R[x]];
}
while(rt[x]>0){
if(p[rt[x]].hs>=rf) break;
if(p[rt[x]].tpe==1) tot[x]++;
gt[++cnt]=rt[x],rt[x]=del(rt[x]);
}
suf[cnt+1]=0,pre[0]=0;
for(int i=1;i<=cnt;i++){
pre[i]=pre[i-1],suf[cnt-i+1]=suf[cnt-i+2];
if(p[gt[i]].tpe==1) pre[i]++;
if(p[gt[cnt-i+1]].tpe==0) suf[cnt-i+1]++;
}
for(int i=0;i<=cnt;i++){
if(p[gt[i]].hs==p[gt[i+1]].hs&&i!=0) continue;
sum=max(sum,pre[i]+suf[i+1]);
}
if(l==r){f[x]=sum;return;}
f[x]=max(f[L[x]]+f[R[x]]+suf[1],tot[L[x]]+tot[R[x]]+sum);
}
int main(){
T=read();
while(T--){
n=read(),m=read(),tmp=ans=tk=0,t[0]=t[n]=2147483646;
memset(fs,0,sizeof(fs));
for(int i=1;i<n;i++) t[i]=read();
for(int i=1;i<=m;i++) p[i].pos=read(),p[i].hs=read(),p[i].tpe=read();
build(1,1,n-1),sort(p+1,p+m+1,cmp);
for(int i=1;i<=m;i++){fs[p[i].pos]=merge(i,fs[p[i].pos]);}
dp(tk,1,n),printf("%d\n",f[tk]);
}
return 0;
}

  

雅礼集训 2017 Day2 水箱 可并堆的更多相关文章

  1. 「雅礼集训 2017 Day2」解题报告

    「雅礼集训 2017 Day2」水箱 我怎么知道这种题目都能构造树形结构. 根据高度构造一棵树,在树上倍增找到最大的小于约束条件高度的隔板,开一个 \(vector\) 记录一下,然后对于每个 \(v ...

  2. #6034. 「雅礼集训 2017 Day2」线段游戏 李超树

    #6034. 「雅礼集训 2017 Day2」线段游戏 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统 ...

  3. 【loj6034】「雅礼集训 2017 Day2」线段游戏

    #6034. 「雅礼集训 2017 Day2」线段游戏 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:Special Judge 上传者: 匿名 题目描述 ...

  4. loj #6032. 「雅礼集训 2017 Day2」水箱 线段树优化DP转移

    $ \color{#0066ff}{ 题目描述 }$ 给出一个长度为 \(n\) 宽度为 \(1\) ,高度无限的水箱,有 \(n-1\) 个挡板将其分为 \(n\) 个 \(1 - 1\) 的小格, ...

  5. 「雅礼集训 2017 Day2」水箱 (数据结构+dp ,一个log)

    题面 题解 在网上看到有些做法,有什么平衡树.启发式合并等等总之复杂度O(Tnlog^2(n))的不优做法,这里我就用一个O(Tnlogn)的做法好了 其实大体上推导的思路都是一样的. 我们很容易发现 ...

  6. loj#6032. 「雅礼集训 2017 Day2」水箱(并查集 贪心 扫描线)

    题意 链接 Sol 神仙题+神仙做法%%%%%%%% 我再来复述一遍.. 首先按照\(y\)坐标排序,然后维护一个扫描线从低处往高处考虑. 一个连通块的内状态使用两个变量即可维护\(ans\)表示联通 ...

  7. LOJ#6032. 「雅礼集训 2017 Day2」水箱

    传送门 首先可以有一个平方复杂度的 \(DP\) 设 \(f_{i,j}\) 表示前面 \(i\) 个小格,高度为 \(j\) 的最大答案 令 \(h_i\) 表示隔板 \(i\) 的高度 当 \(j ...

  8. 「雅礼集训 2017 Day2」水箱

    题目链接 题意分析 我们用\(f[i][j]\)表示当前到达第\(i\)个位置水位高度为\(j\)的答案 如果那么\(h[i]\)为\(i\)和\(i+1\)之间的支柱高度 那么如果\(j≤h[i]\ ...

  9. loj#6033. 「雅礼集训 2017 Day2」棋盘游戏(二分图博弈)

    题意 链接 Sol 第一次做在二分图上博弈的题..感觉思路真是清奇.. 首先将图黑白染色. 对于某个点,若它一定在最大匹配上,那么Bob必胜.因为Bob可以一直沿着匹配边都,Alice只能走非匹配边. ...

随机推荐

  1. ios - 使用@try、catch捕获异常:

    @try { // 可能会出现崩溃的代码 } @catch (NSException *exception) { // 捕获到的异常exception } @finally { // 结果处理 }

  2. table中tr的display属性在火狐中显示不正常,IE中显示正常

    最近在作项目的时候碰到一个问题,就是需要AJAX来交互显示<tr> </tr> 标签内的东西,按照常理,对于某一单元行需要显示时,使用:display:block属性,不需要显 ...

  3. 九度OJ 1205:N阶楼梯上楼问题 (斐波那契数列)

    时间限制:1 秒 内存限制:128 兆 特殊判题:否 提交:3739 解决:1470 题目描述: N阶楼梯上楼问题:一次可以走两阶或一阶,问有多少种上楼方式.(要求采用非递归) 输入: 输入包括一个整 ...

  4. android在activity中去掉标题栏

    package com.goodness.goodness; import android.support.v7.app.AppCompatActivity; import android.os.Bu ...

  5. (转)Web Service和WCF的到底有什么区别

    [1]Web Service:严格来说是行业标准,也就是Web Service 规范,也称作WS-*规范,既不是框架,也不是技术. 它有一套完成的规范体系标准,而且在持续不断的更新完善中. 它使用XM ...

  6. python 发送邮件的两种方式【终极篇】

    一,利用python自带的库 smtplib简单高效 from email.mime.multipart import MIMEMultipart from email.mime.text impor ...

  7. python基础20 -------python中的异常处理

    一.python程序中的会出现的错误. 1.语法错误:这种错误根本过不了python解释器的语法检测阶段,必须在程序执行之前进行改正. 2.逻辑错误:这种错误虽然过了语法检测阶段但是程序在执行的过程中 ...

  8. KinedEditor特性

    谷歌浏览器会将kindeditor在其他js文件加载完之后加载 kindeditor是异步加载,document.ready完了,kindeditor可能还没加载完 kind会将选区变成一个节点 1. ...

  9. Android SDK上手指南 2:用户界面设计

    http://mobile.51cto.com/ahot-419184.htm 内容简介 我们将为应用程序项目添加布局方案,在这方面XML与Eclipse ADT接口将成为工作中的得力助手——不过在后 ...

  10. 【leetcode刷题笔记】Longest Common Prefix

    Write a function to find the longest common prefix string amongst an array of strings. 题解:以strs[0]为模 ...