hdu5575 Discover Water Tank
题意:
给出个水箱,水箱两侧有无限高的隔板,水箱内有整数高度的隔板将水箱分成n-1份,现在给出m个限制,每个限制表示某个位置的某个高度有水或没水,问最多能同时满足多少个限制.n,m<=2*10^5
分析:
“某个位置有水”的限制会导致从这个位置向两侧扩展的一个区间都有这个高度的水.只要找到从这个位置向左/向右第一个比这个限制的水位高的挡板即可,可以用单调栈+二分O(nlogn)求出所有区间,每个区间对应有一个高度(就是这个限制的水位高度).如果某个有水的区间对应的高度下方有一个位置存在”这个位置不能有水”的限制,那么这两个不同种类的限制就会产生矛盾,两个有矛盾的限制不能同时满足,一些限制如果两两不存在矛盾那么就可以同时满足,而且只有不同种类的限制才会产生矛盾,那么这是一个二分图最大独立集的模型,我们就可以打一个网络流暴力
仔细分析一下,我们发现两个不同的有水的限制所对应的区间要么相互包含,要么相互没有公共部分,要么完全相同.假设出现了相交但不包含的情况,不妨令两个区间为[l1,r1]和[l2,r2],且l1<l2<r1<r2,那么l1和r1一定比[l1,r1]内部的挡板高,l2和r2一定比[l2,r2]内部的挡板高,第一个限制如果越过了l2,就不应该被r1挡住,第二个限制如果越过了r1,就不应该被l2挡住.因此所有区间要么相互包含要么相互独立.
这样,所有区间的包含关系形成了一个森林结构,可以加一个超级根连成一棵树.
那么我们如果让某个有水区间的限制满足,那么这个区间所"包含(即:横坐标范围不超出这个区间且高度在这个区间下方)"的所有区间都必须有水,而且这个区间下方所有的"没水"的限制都不能满足.最后我们肯定会选出某些子树,满足这些子树内的"有水"限制且放弃这些子树的根节点覆盖的"无水"限制(根节点的区间的覆盖范围是最大的).
那么将所有限制按高度排序,扫描一遍,用树状数组求出每个区间覆盖的"无水"限制的个数,用平衡树维护一下区间,把树形结构建立出来就可以了.
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cctype>
using namespace std;
void read(int &x){
char ch;while(ch=getchar(),!isdigit(ch));
x=ch-'';
while(ch=getchar(),isdigit(ch))x=x*+ch-'';
}
const int maxn=;
vector<int> num[maxn];
int n,m;
int h[maxn];
int l[maxn],r[maxn];
int x[maxn],y[maxn],typ[maxn];
int binary(int *stk,int l,int r,int x){
while(l<=r){
int mid=(l+r)>>;
if(h[stk[mid]]>=x)l=mid+;
else r=mid-;
}
return stk[l-];
}
void init(){
static int stk[maxn],top=;
top=;
for(int i=;i<=n;++i){
num[i].clear();
}
for(int i=;i<=m;++i){
if(typ[i]==)num[x[i]].push_back(i);
}
stk[top++]=;
for(int i=;i<=n;++i){
for(vector<int>::iterator pt=num[i].begin();pt!=num[i].end();++pt){
l[(*pt)]=binary(stk,,top-,y[*pt]+);
}
while(h[stk[top-]]<h[i]){
top--;
}
stk[top++]=i;
}
top=;stk[top++]=n;
for(int i=n;i>=;--i){
for(vector<int>::iterator pt=num[i].begin();pt!=num[i].end();++pt){
r[*pt]=binary(stk,,top-,y[*pt]+);
}
while(h[stk[top-]]<h[i-]){
top--;
}
stk[top++]=i-;
}
}
int sum[maxn];//sum[i]:limitation i of typ1 contain how many limatation of typ0
int c[maxn];
void add(int x){
for(;x<maxn;x+=x&(-x))c[x]++;
}
int pre(int x){
int ans=;
for(;x;x-=x&(-x))ans+=c[x];
return ans;
}
int seq[maxn];
bool cmp(const int &a,const int &b){
return (y[a]==y[b])?typ[a]<typ[b]:y[a]<y[b];
}
struct edge{
int to,next;
}lst[maxn<<];int first[maxn],len=;
void addedge(int a,int b){
lst[len].to=b;lst[len].next=first[a];first[a]=len++;
}
struct node{
int l,r,num,ord,sz;
node* ch[];
node(){}
node(int L,int R,int N){
ch[]=ch[]=;
l=L;r=R;num=N;ord=rand();sz=;
}
void update(){
sz=;
if(ch[])sz+=ch[]->sz;
if(ch[])sz+=ch[]->sz;
}
}t[maxn*];int tsz=;
node* newnode(int L,int R,int x){
t[++tsz]=node(L,R,x);return t+tsz;
}
void rot(node* &rt,int t){
node* c=rt->ch[t];rt->ch[t]=c->ch[t^];c->ch[t^]=rt;rt=c;
c->ch[t^]->update();c->update();
}
void Insert(node* &rt,int x){
if(!rt)rt=newnode(l[x]+,r[x],x);
else{
int t=(l[x]+)>rt->l;
Insert(rt->ch[t],x);
rt->update();
if(rt->ch[t]->ord>rt->ord)rot(rt,t);
}
}
node* succ(node* rt,int x){
if(!rt)return ;
if(rt->l>=l[x]+){
node* tmp=succ(rt->ch[],x);
if(tmp)return tmp;
else return rt;
}else{
return succ(rt->ch[],x);
}
}
node* root;
void remove(node* &rt,int l){
if(rt->l!=l){
remove(rt->ch[l>rt->l],l);
rt->update();
}else{
if(!rt->ch[])rt=rt->ch[];
else if(!rt->ch[])rt=rt->ch[];
else{
if(rt->ch[]->ord>rt->ch[]->ord){
rot(rt,);remove(rt->ch[],l);
}else{
rot(rt,);remove(rt->ch[],l);
}
rt->update();
}
}
}
void traverse(node* rt){
if(!rt)return;
addedge(,rt->num);
traverse(rt->ch[]);traverse(rt->ch[]);
}
int sz[maxn],f[maxn];
void dp(int x){
if(x)sz[x]=;
else sz[x]=;
int tmp=;
for(int pt=first[x];pt;pt=lst[pt].next){
dp(lst[pt].to);sz[x]+=sz[lst[pt].to];
tmp+=max(f[lst[pt].to],);
}
f[x]=max(tmp,sz[x]-sum[x]);
}
int main(){
int cases=;
int tests;read(tests);
while(tests--){
root=;tsz=;
memset(c,,sizeof(c));
memset(first,,sizeof(first));len=;
read(n);read(m);
int cnt0=;
for(int i=;i<n;++i)scanf("%d",&h[i]);
for(int i=;i<=m;++i){
read(x[i]);read(y[i]);read(typ[i]);
if(typ[i]==)cnt0++;
}
h[]=h[n]=0x7f7f7f7f;
init();
for(int i=;i<=m;++i)seq[i]=i;
sort(seq+,seq+m+,cmp);
for(int i=;i<=m;++i){
if(typ[seq[i]]==)add(x[seq[i]]);
else{
sum[seq[i]]=pre(r[seq[i]])-pre(l[seq[i]]);
node* pt;
while((pt=succ(root,seq[i]))&&pt->r<=r[seq[i]]){
addedge(seq[i],pt->num);
remove(root,pt->l);
}
Insert(root,seq[i]);
}
}
sum[]=pre(n);
traverse(root);
dp();
printf("Case #%d: %d\n",++cases,cnt0+f[]);
}
return ;
}
hdu5575 Discover Water Tank的更多相关文章
- 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
题意: 有一个水槽,边界的两块板是无穷高的,中间有n-1块隔板(有高度),现有一些条件(i,y,k),表示从左到右数的第i列中,在高度为(y+0.5)的地方是否有水(有水:k = 1),问最多能同时满 ...
- CF414D Mashmokh and Water Tanks
CF414D Mashmokh and Water Tanks 洛谷评测传送门 题目描述 Mashmokh is playing a new game. In the beginning he has ...
- PID控制器(比例-积分-微分控制器)- I
形象解释PID算法 小明接到这样一个任务: 有一个水缸点漏水(而且漏水的速度还不一定固定不变),要求水面高度维持在某个位置,一旦发现水面高度低于要求位置,就要往水缸里加水. 小明接到任务后就一直守在水 ...
- ZOJ 5579 Stean
Stean Time Limit: 1 Second Memory Limit: 65536 KB Special Judge Tom is good at making stea ...
- CodeForces 362E Petya and Pipes
Petya and Pipes Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on CodeForces. ...
- What are CBR, VBV and CPB?
转自:https://codesequoia.wordpress.com/2010/04/19/what-are-cbr-vbv-and-cpb/ It's common mistake to to ...
- Aquarium Tank(csu1634+几何+二分)Contest2087 - 湖南多校对抗赛(2015.05.24)-G
Aquarium Tank Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 15 Solved: 4[Submit][Status][Web Board ...
- [LeetCode] Pacific Atlantic Water Flow 太平洋大西洋水流
Given an m x n matrix of non-negative integers representing the height of each unit cell in a contin ...
随机推荐
- 状压搜索 洛谷T47092 作业
TYM 有 nn 本作业,编号为 1,\dots,n1,…,n. 由于 \mathrm{TYM}TYM 很喜欢偷懒,而且不喜欢消耗脑细胞,所以他选择跳着完成这 nn 本作业.此外,如果将做作业的顺序转 ...
- Ubuntu 安装 搜狗输入法
1.去下载搜狗输入法安装包: https://pinyin.sogou.com/linux/ 2.安装 sudo dpkg sougou****.deb 3.去设置 参考:https://blog.c ...
- VINS(五)非线性优化与在线标定调整
首先根据最大后验估计(Maximum a posteriori estimation,MAP)构建非线性优化的目标函数. 初始化过程通过线性求解直接会给出一个状态的初值,而非线性优化的过程关键在于求解 ...
- netty之管道处理流程
1.我们在使用netty的是有都会存在将channelBuffer的数据处理成相应的String或者自定义数据.而这里主要是介绍管道里面存在的上行和下行的数据处理方式 2.通过一张图片来看一下具体管道 ...
- Hadoop3.0新特性
1. Hadoop3.0简介 Hadoop 2.0是基于JDK 1.7开发的,而JDK 1.7在2015年4月已停止更新,这直接迫使Hadoop社区基于JDK1.8重新发布一个新的Hadoop版本,而 ...
- redis 类型、方法
之前使用redis,现在对所有redis方法做一个总结: string类型 形式:key=>value; 说明:最简单的类型:一个key对应一个value,value保存的类型是二进制安全的,s ...
- centos7系统配置系统用户基于ssh的google身份验证
最近也是服务器各种被入侵,所以在安全上,要万分注意,特此记录,借助google的身份验证插件,获取动态验证码完成ssh登陆. OS: centos7 安装配置: 1. 安装epel源 yum -y i ...
- Ubuntu卡在logo界面
对于这个问题,我也是在最近一次偶然的机会中发现的. 我重装了了Ubuntu 18.04, 很多东西需要重新配置, 有个刚性需求就是配置shadowsocks实现***,对于从windows向linu ...
- 前端开发工程师 - 01.页面制作 - 第3章.HTML
第3章--HTML HTML简介 Hyper Text Markup Language:超文本标记语言--用于标记网页的内容 history: html(1991)雏形 -> html4.01( ...
- * 197. Permutation Index【LintCode by java】
Description Given a permutation which contains no repeated number, find its index in all the permuta ...