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-'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相关推荐
- HDU5575 Discover Water Tank 2015上海现场赛D题 (树形dp,并查集,左偏树)
题目大意: 有一个1维的长度为N,高度无限的水柜,现在要用N-1个挡板将其分为N个长度为1的小格,然后向水柜中注水,水可以低于挡板也可以以溢出去(这样就要与旁边格子的水位相同),现在有M次探测,探测i ...
- 线段树合并(HDU-5575 Discover Water Tank)
题目连接 题意: 给你一个长为n,宽为1,高为无穷的水缸.里面有n-1个高度不一的隔板隔开为1x1大小的区域.里面的水遵循物理定理.给你m次查询和回应,每个查询<x,y,z>.代表查询第x ...
- hdu 5575 Discover Water Tank(可合并堆)
题目链接:hdu 5575 Discover Water Tank 题意: 有一个大水箱,里面有N-1个隔板,将这个大水箱分成了N个小水箱,每个隔板有一定的高度. 现在有m条信息,每条信息表示第x个水 ...
- HDU--5575、Discover Water Tank (思维、优先队列)
题目链接 题面: 题意: 有一个 1∗n1*n1∗n 的水箱,水箱的四周的高度为无穷大.现在用 n−1n-1n−1 高度为 hih_ihi 的隔板将水箱分为 nnn 个 1∗11*11∗1 的部分. ...
- 树形DP+并查集+左偏树, HDU-5575,Discover Water Tank,2015上海现场赛D题
只是ACM/IICPC 2015 上海区域赛的一道题.原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5575 题目描述 N-1个木板把一个水箱划分成了N ...
- HDU 5575 Discover Water Tank(左偏树)
https://vjudge.net/problem/HDU-5575 题意: 有一个水箱,被n-1块板子分成了n个部分,板子的高度不尽相同.现在有m次探测,每次探测在第x部分的y+0.5高度处是否有 ...
- hdu 5575 Discover Water Tank 左偏树
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5575 题意: 现在有一个巨大的水库(可视为二维的),水库中间被 n−1n-1n−1 个挡板分成了 n ...
- HDU 5575 Discover Water Tank
原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5575 把每个水箱当作一个并查集,每个无水的探测当做一个左偏树.有水的探测则放在数组中.并用一个数组使水 ...
- HDU 5575 Discover Water Tank 并查集 树形DP
题意: 有一个水槽,边界的两块板是无穷高的,中间有n-1块隔板(有高度),现有一些条件(i,y,k),表示从左到右数的第i列中,在高度为(y+0.5)的地方是否有水(有水:k = 1),问最多能同时满 ...
最新文章
- android数据库查找一个字符,Android - 如何在Firebase数据库中对字符串进行简单搜索?_android_开发99编程知识库...
- 精通Python网络爬虫:核心技术、框架与项目实战.1.1 初识网络爬虫
- Facebook Messenger要点燃聊天机器人革命,据说四月就发布!
- Mysql安装注意问题
- 图像白化MATLAB代码实现
- 大脚导入配置选择哪个文件_有史以来最全的 IntelliJ IDEA 配置图解
- elxel表格纸张尺寸_一本书的诞生:纸张知识
- java 看虚拟机内存_java 虚拟机内存介绍
- Python 2.7 将在 2020 年终止所有支持!
- Google 发布全中文机器学习速成课,曾内部培训过 1.8 万人!
- mysql,SQL标准,多表查询中内连接,外连接,自然连接等详解之查询结果集的笛卡尔积的演化...
- 有基础学python看什么书好_python入门学习看什么书好,有什么书籍推荐
- 旅游后台管理系列——使用maven tomcat插件启动web工程
- 华为云UGO正式亮相DTCC 2021,去“O”从此再无后顾之忧
- 一天完成写出一篇毕业设计论文(2020年版本)
- 大数据学习一般学什么
- webgis技术在智慧城市综合治理(9+X)网格化社会管理平台(综治平台)的应用研究...
- 深度剖析ROC曲线以及AUC指标
- 【Linux系统中的】虚拟机的安装管理及虚拟机快照的建立
- 托福高频真词List03 // 附阅读真题
热门文章
- 利用OpenStreetMap决定GPS点所在的道路类型
- 键盘快捷键发送与输入法按键冲突
- Hive,sha256,md5实例
- java 创建gbase_GBase8s + MyBatis 操作示例
- js 实现完整版淘宝购物车
- 计算机网络工程师能力优势,考网络工程师的优势方法?
- rosdep安装与使用
- AEC——智慧物流管理系统
- 暴风php视频怎么打开,暴风影音飞屏怎么用?暴风影影音飞屏功能及使用方法图文详解...
- python条形码生成_python3转换code128条形码