UOJ356 [JOI2017春季合宿] Port Facility 【启发式合并】【堆】【并查集】
题目分析:
好像跑得很快,似乎我是第一个启发式合并的。
把玩具看成区间。首先很显然如果有两个玩具的进出时间有$l1<l2<r1<r2$的关系,那么这两个玩具一定在不同的栈中间。
现在假设一定有解,我们怎么得到答案呢?排序会使得计算变得方便,下面我们按照左端点排序。
想象一条扫描线,从左往右,当它遇到了一个区间的左端点的时候,我们尝试着将原先不在一起的合并,所有和这个不同栈的都被合并。
我们可以想象一个并查集,使用堆维护并查集。堆内存储并查集内元素的右端点。在最外面再用一个大堆来存储每个并查集的右端最小值(堆套堆)
实际上在每个并查集唯一要考虑的是在当前扫描线右端的最小的点的位置。若它不在当前玩具控制的区间内则该并查集一定不被该玩具影响。
否则将它提取出来,然后对并查集启发式合并。不仅如此,当前考虑的玩具也被合并在内。
现在考虑无解。无解实际上是冲突,如果有两个互异玩具集合,如果新出现一个玩具和其它两个不兼容则无解。
在上面的基础上,我们要做的只有把一个并查集再分裂成两个部分,然后两个部分分开合并即可。
时间复杂度$O(nlogn)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef pair<int,int> pr; 4 5 const int maxn = (1<<21)+5; 6 const int mod = 1000000007; 7 struct line{int l,r,num;}A[maxn]; 8 int cnt,n,im[maxn]; 9 10 void read(){ 11 scanf("%d",&n); 12 for(int i=1;i<=n;i++)scanf("%d%d",&A[i].l,&A[i].r),A[i].num=i; 13 sort(A+1,A+n+1,[](line a,line b){return a.l < b.l;}); 14 } 15 16 priority_queue<pr,vector<pr>,greater<pr> > pq; 17 priority_queue<int,vector<int>,greater<int> > s[maxn>>1],t[maxn>>1]; 18 int um,rs[maxn],num; 19 void work(){ 20 for(int i=1;i<=n;i++) s[i].push(A[i].r); 21 for(int i=1;i<=n;i++){ 22 while(!pq.empty()){ 23 pr k = pq.top(); if(k.first > A[i].l) break; pq.pop(); 24 if(s[k.second].size() && s[k.second].top() == k.first) s[k.second].pop(); 25 else t[k.second].pop(); 26 if(!s[k.second].size() && !t[k.second].size()) cnt++; 27 else{ 28 if(!t[k.second].size()) {pq.push(make_pair(s[k.second].top(),k.second));continue;} 29 if(!s[k.second].size()) {pq.push(make_pair(t[k.second].top(),k.second));continue;} 30 if(s[k.second].size() && t[k.second].size()) 31 pq.push(make_pair(min(s[k.second].top(),t[k.second].top()),k.second)); 32 } 33 } 34 if(pq.empty()){pq.push(make_pair(A[i].r,i));continue;} 35 um = i;int place = 0;num = 0; 36 while(!pq.empty()){pr k = pq.top();if(k.first < A[i].r) {rs[++num] = k.second;pq.pop();}else break;} 37 for(int j=1;j<=num;j++){ 38 int zeta = rs[j]; 39 if(s[zeta].size() && t[zeta].size() && s[zeta].top() < A[i].r && t[zeta].top() < A[i].r){ 40 puts("0");return; 41 } 42 int sum1 = s[um].size() + t[um].size(),sum2 = s[zeta].size()+t[zeta].size(); 43 if(sum1 > sum2){ 44 if((s[zeta].size() && s[zeta].top() < A[i].r) ^ place){ 45 while(t[zeta].size()){s[um].push(t[zeta].top());t[zeta].pop();} 46 while(s[zeta].size()){t[um].push(s[zeta].top());s[zeta].pop();} 47 } 48 else{ 49 while(s[zeta].size()){s[um].push(s[zeta].top());s[zeta].pop();} 50 while(t[zeta].size()){t[um].push(t[zeta].top());t[zeta].pop();} 51 } 52 }else{ 53 if((s[zeta].size() && s[zeta].top() < A[i].r) ^ place){ 54 while(t[um].size()){s[zeta].push(t[um].top());t[um].pop();} 55 while(s[um].size()){t[zeta].push(s[um].top());s[um].pop();} 56 place ^= 1; 57 }else{ 58 while(s[um].size()){s[zeta].push(s[um].top());s[um].pop();} 59 while(t[um].size()){t[zeta].push(t[um].top());t[um].pop();} 60 } 61 um = zeta; 62 } 63 } 64 if(!t[um].size())pq.push(make_pair(s[um].top(),um)); 65 else if(!s[um].size()) pq.push(make_pair(t[um].top(),um)); 66 else pq.push(make_pair(min(s[um].top(),t[um].top()),um)); 67 } 68 while(!pq.empty()){cnt++;pq.pop();} 69 int ans = 1;while(cnt--){ans*=2;ans%=mod;} 70 printf("%d",ans); 71 } 72 73 int main(){ 74 read(); 75 work(); 76 return 0; 77 }
转载于:https://www.cnblogs.com/Menhera/p/9277444.html
UOJ356 [JOI2017春季合宿] Port Facility 【启发式合并】【堆】【并查集】相关推荐
- ccpc长春-K. Ragdoll(启发式合并、并查集、gcd转化)map的神奇tle
K. Ragdoll 菜死我得了 题意:给定一组点以及他们的权重(1⩽n⩽1051\leqslant n\leqslant10^51⩽n⩽105),起初所有点都是独立的点.给定三种操作: 1xv1\ ...
- 【JOI2017春季合宿】Port Facility
http://uoj.ac/problem/356 题解 思路和\(NOIP\)双栈排序差不多. 对于两个元素,若\(l_1<l_2<r_1<r_2\)那么它们不能在一个栈里,我们连 ...
- JOI2017 春季合宿:Railway Trip
自己的AC做法似乎离正解偏了十万八千里而且复杂了不少--不管怎样还是记录下来吧. 题意: 题目链接: JOISC2017 F - AtCoder JOISC2017 F - LOJ \(N\)个车站排 ...
- 2021牛客OI赛前集训营-树数树【树上启发式合并,堆】
正题 题目链接:https://ac.nowcoder.com/acm/contest/20107/C 题目大意 给出nnn个点的一棵树,求一个最长的序列使得数字互不相同且相邻编号节点的都是祖孙关系. ...
- JOI-2016/17 春季合宿 切题记
17年的合宿好难啊...感觉是我做过的最难的一套题(没有之一)了...但是可能也是价值最高的? Day1: T1 Cultivation:给你一个H*W的网格,有N<=300棵仙人掌.每一年可以 ...
- BZOJ 4388 [JOI2012春季合宿]Invitation (线段树、二叉堆、最小生成树)
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4388 题解 模拟Prim算法? 原题所述的过程就是Prim算法求最大生成树的过程.于是我 ...
- BZOJ 4221 [JOI2012春季合宿]Kangaroo (DP)
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4221 题解 orz WYC 爆切神仙DP 首先将所有袋鼠按大小排序.考虑从前往后DP, ...
- LOJ #2731 [JOI2016春季合宿]Solitaire (DP、组合计数)
题目链接 https://loj.ac/problem/2731 题解 首先一个很自然的思路是,设\(dp[i][j]\)表示选了前\(i\)列,第\(2\)行第\(i\)列的格子是第\(j\)个被填 ...
- LOJ #2733 [JOI2016春季合宿]Sandwiches (DP)
题目链接 https://loj.ac/problem/2733 题解 神仙题-- 首先可以观察到一个结论: 目标块的两块小三明治一定分别是最后和倒数第二个被吃的. 由此我们可以考虑这两块谁先被吃.这 ...
- LOJ #2734 Luogu P3615 [JOI2016春季合宿]Toilets (结论、贪心)
题目链接 (loj) https://loj.ac/problem/2734 (luogu) https://www.luogu.org/problem/P3615 题解 嗯,考场上肝了\(3h\)然 ...
最新文章
- 转载-致IT同仁 —— IT人士常犯的17个职场错误
- 表盘时针的html代码,html5画布操作的简单学习-简单时钟
- 在线图表编辑工具 draw.io 10.6.5 版本发布
- php数据库删除数据,php数据库删除数据的简单示例
- ubuntu下kaldi的安装以及实例的运行
- apache是怎么运行php的_PHP与WEB服务器是如何交互的
- [debug] Expected to have finished reduction in the prior iteration before starting a new one.
- [iOS] 使用xib做为应用程序入口 with Code
- python有哪几种数据结构_Python最常用的数据结构6种
- 移动设备如何当作FL Studio中的MIDI控制器(下)
- Java游戏框架编写
- Mysql监控工具小集合
- laravel excel 导出图片
- 计算机中sumif函数的使用方法,WPS表格的sumif函数用法与模糊条件使用方法
- Atcoder ABC162 D - RGB Triplets
- 工业相机基本参数以及选型参考(二)
- HBase hmaster无法正常启动,日志报错Operation category READ is not supported in state standby.hdfs ha hbase配置修改
- 再见 xxl-job!更强大的新一代分布式任务调度框架来了
- 大数据时代:我们的邮件被谁偷看了?
- AES 和 SM4 S盒复合域实现方法
热门文章
- matlab求函数方程的正根,matlab解方程组的时候,可以只要正根吗?
- printline在C语言中的作用,iswprint - [ C语言中文开发手册 ] - 在线原生手册 - php中文网...
- 日期范围选择类日历(增强版)
- Linux系统中运行jar包的四种方式
- mybatis的缓存基础
- php 字符转ansi,php 字符编码转换类,支持ANSI、Unicode、Unicode big endian、UTF-8、UTF-8+Bom 互相转换...
- 域名访问html乱码,显示地址和域名解析时出现乱码
- 基于springboot+LayUI的校园信息发布平台
- java练手小程序_Java小程序练习
- 两个页面用url传值 和设置页面字段为不可编辑或是只读