题意:

给出个水箱,水箱两侧有无限高的隔板,水箱内有整数高度的隔板将水箱分成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-'0';while(ch=getchar(),isdigit(ch))x=x*10+ch-'0';
}
const int maxn=200005;
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)>>1;if(h[stk[mid]]>=x)l=mid+1;else r=mid-1;}return stk[l-1];
}
void init(){static int stk[maxn],top=0;top=0;for(int i=1;i<=n;++i){num[i].clear();}for(int i=1;i<=m;++i){if(typ[i]==1)num[x[i]].push_back(i);}stk[top++]=0;for(int i=1;i<=n;++i){for(vector<int>::iterator pt=num[i].begin();pt!=num[i].end();++pt){l[(*pt)]=binary(stk,0,top-1,y[*pt]+1);}while(h[stk[top-1]]<h[i]){top--;}stk[top++]=i;}top=0;stk[top++]=n;for(int i=n;i>=1;--i){for(vector<int>::iterator pt=num[i].begin();pt!=num[i].end();++pt){r[*pt]=binary(stk,0,top-1,y[*pt]+1);}while(h[stk[top-1]]<h[i-1]){top--;}stk[top++]=i-1;}
}
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=0;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<<1];int first[maxn],len=1;
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[2];node(){}node(int L,int R,int N){ch[0]=ch[1]=0;l=L;r=R;num=N;ord=rand();sz=1;}void update(){sz=1;if(ch[0])sz+=ch[0]->sz;if(ch[1])sz+=ch[1]->sz;}
}t[maxn*2];int tsz=0;
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^1];c->ch[t^1]=rt;rt=c;c->ch[t^1]->update();c->update();
}
void Insert(node* &rt,int x){if(!rt)rt=newnode(l[x]+1,r[x],x);else{int t=(l[x]+1)>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 0;if(rt->l>=l[x]+1){node* tmp=succ(rt->ch[0],x);if(tmp)return tmp;else return rt;}else{return succ(rt->ch[1],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[0])rt=rt->ch[1];else if(!rt->ch[1])rt=rt->ch[0];else{if(rt->ch[0]->ord>rt->ch[1]->ord){rot(rt,0);remove(rt->ch[1],l);}else{rot(rt,1);remove(rt->ch[0],l);}rt->update();}}
}
void traverse(node* rt){if(!rt)return;addedge(0,rt->num);traverse(rt->ch[0]);traverse(rt->ch[1]);
}
int sz[maxn],f[maxn];
void dp(int x){if(x)sz[x]=1;else sz[x]=0;int tmp=0;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],0);}f[x]=max(tmp,sz[x]-sum[x]);
}
int main(){int cases=0;int tests;read(tests);while(tests--){root=0;tsz=0;memset(c,0,sizeof(c));memset(first,0,sizeof(first));len=1;read(n);read(m);int cnt0=0;for(int i=1;i<n;++i)scanf("%d",&h[i]);for(int i=1;i<=m;++i){read(x[i]);read(y[i]);read(typ[i]);if(typ[i]==0)cnt0++;}h[0]=h[n]=0x7f7f7f7f;init();for(int i=1;i<=m;++i)seq[i]=i;sort(seq+1,seq+m+1,cmp);for(int i=1;i<=m;++i){if(typ[seq[i]]==0)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[0]=pre(n);traverse(root);dp(0);printf("Case #%d: %d\n",++cases,cnt0+f[0]);}return 0;
}

转载于:https://www.cnblogs.com/liu-runda/p/6621094.html

hdu5575 Discover Water Tank相关推荐

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

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

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

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

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

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

  4. HDU--5575、Discover Water Tank (思维、优先队列)

    题目链接 题面: 题意: 有一个 1∗n1*n1∗n 的水箱,水箱的四周的高度为无穷大.现在用 n−1n-1n−1 高度为 hih_ihi​ 的隔板将水箱分为 nnn 个 1∗11*11∗1 的部分. ...

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

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

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

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

  7. hdu 5575 Discover Water Tank 左偏树

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

  8. HDU 5575 Discover Water Tank

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

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

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

最新文章

  1. android数据库查找一个字符,Android - 如何在Firebase数据库中对字符串进行简单搜索?_android_开发99编程知识库...
  2. 精通Python网络爬虫:核心技术、框架与项目实战.1.1 初识网络爬虫
  3. Facebook Messenger要点燃聊天机器人革命,据说四月就发布!
  4. Mysql安装注意问题
  5. 图像白化MATLAB代码实现
  6. 大脚导入配置选择哪个文件_有史以来最全的 IntelliJ IDEA 配置图解
  7. elxel表格纸张尺寸_一本书的诞生:纸张知识
  8. java 看虚拟机内存_java 虚拟机内存介绍
  9. Python 2.7 将在 2020 年终止所有支持!
  10. Google 发布全中文机器学习速成课,曾内部培训过 1.8 万人!
  11. mysql,SQL标准,多表查询中内连接,外连接,自然连接等详解之查询结果集的笛卡尔积的演化...
  12. 有基础学python看什么书好_python入门学习看什么书好,有什么书籍推荐
  13. 旅游后台管理系列——使用maven tomcat插件启动web工程
  14. 华为云UGO正式亮相DTCC 2021,去“O”从此再无后顾之忧
  15. 一天完成写出一篇毕业设计论文(2020年版本)
  16. 大数据学习一般学什么
  17. webgis技术在智慧城市综合治理(9+X)网格化社会管理平台(综治平台)的应用研究...
  18. 深度剖析ROC曲线以及AUC指标
  19. 【Linux系统中的】虚拟机的安装管理及虚拟机快照的建立
  20. 托福高频真词List03 // 附阅读真题

热门文章

  1. 利用OpenStreetMap决定GPS点所在的道路类型
  2. 键盘快捷键发送与输入法按键冲突
  3. Hive,sha256,md5实例
  4. java 创建gbase_GBase8s + MyBatis 操作示例
  5. js 实现完整版淘宝购物车
  6. 计算机网络工程师能力优势,考网络工程师的优势方法?
  7. rosdep安装与使用
  8. AEC——智慧物流管理系统
  9. 暴风php视频怎么打开,暴风影音飞屏怎么用?暴风影影音飞屏功能及使用方法图文详解...
  10. python条形码生成_python3转换code128条形码