题目分析:

好像跑得很快,似乎我是第一个启发式合并的。

把玩具看成区间。首先很显然如果有两个玩具的进出时间有$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 = (<<)+;
  6. const int mod = ;
  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=;i<=n;i++)scanf("%d%d",&A[i].l,&A[i].r),A[i].num=i;
  13. sort(A+,A+n+,[](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>>],t[maxn>>];
  18. int um,rs[maxn],num;
  19. void work(){
  20. for(int i=;i<=n;i++) s[i].push(A[i].r);
  21. for(int i=;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 = ;num = ;
  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=;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("");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 ^= ;
  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 = ;while(cnt--){ans*=;ans%=mod;}
  70. printf("%d",ans);
  71. }
  72.  
  73. int main(){
  74. read();
  75. work();
  76. return ;
  77. }

UOJ356 [JOI2017春季合宿] Port Facility 【启发式合并】【堆】【并查集】的更多相关文章

  1. [JOI2017春季合宿]Port Facility[set、二分图]

    题意 你有两个栈,有 \(n\) 个货物,每个货物有一个进栈时间和出栈时间(所有时间的并集是1~2n),问有多少种不同的入栈方案. \(n\le 10^6\) 分析 把每个货物的存在看成区间,相交的区 ...

  2. BZOJ 2733 [HNOI2012]永无乡(启发式合并+Treap+并查集)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2733 [题目大意] 给出n个点,每个点都有自己的重要度,现在有连边操作和查询操作, 查 ...

  3. UOJ356 【JOI2017春季合宿】Port Facility

    暴力就是O(n^2)连边,二分图,这样只有22分. 我们考虑优化建边,我们按照左端点排序,对于一个新加进来的线段,我们向左端点距其最近的和他相交的线段连边,别的相交的我们连同色边,当一个点连了两条同色 ...

  4. UOJ #356. 【JOI2017春季合宿】Port Facility

    Description 小M有两个本质不同的栈. 无聊的小M找来了n个玩具.之后小M把这n个玩具随机顺序加入某一个栈或把他们弹出. 现在小M告诉你每个玩具的入栈和出栈时间,现在她想考考小S,有多少种方 ...

  5. 【JOI2017春季合宿】Port Facility

    http://uoj.ac/problem/356 题解 思路和\(NOIP\)双栈排序差不多. 对于两个元素,若\(l_1<l_2<r_1<r_2\)那么它们不能在一个栈里,我们连 ...

  6. UOJ #357. 【JOI2017春季合宿】Sparklers

    Description 小S和小M去看花火大会. 一共有 n 个人按顺序排成一排,每个人手上有一个仅能被点燃一次的烟花.最开始时第 K 个人手上的烟花是点燃的. 烟花最多能燃烧 T 时间.每当两个人的 ...

  7. JOI2017 春季合宿:Railway Trip

    自己的AC做法似乎离正解偏了十万八千里而且复杂了不少--不管怎样还是记录下来吧. 题意: 题目链接: JOISC2017 F - AtCoder JOISC2017 F - LOJ \(N\)个车站排 ...

  8. BZOJ 4388 [JOI2012春季合宿]Invitation (线段树、二叉堆、最小生成树)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4388 题解 模拟Prim算法? 原题所述的过程就是Prim算法求最大生成树的过程.于是我 ...

  9. BZOJ 4221 [JOI2012春季合宿]Kangaroo (DP)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4221 题解 orz WYC 爆切神仙DP 首先将所有袋鼠按大小排序.考虑从前往后DP, ...

随机推荐

  1. JS实现一个v-if

    // 获取dom var el = document.getElementById('root'); console.log(el); // 遍历dom function dealNode(el) { ...

  2. flask登录插件 flask-login

    Flask-Login为Flask提供了用户会话管理,它处理了日常的登入登出且长时间记住用户的会话 使用: 1.配置,初始化 LoginManager 创建实例 loginManger = Login ...

  3. java 类与类,类与接口 ,接口与接口关系

    类: 生活中类是人们对客观事物不断认识而产生的抽象概念,而对象则是现实生活中的一个个实体 面向对象程序设计中,对象是程序的基本单位,相似的对象像变量和类型的关系一样归并到一类,所以,并不先具体地定义对 ...

  4. JS 面向对象 ~ 创建对象的 9 种方式

    一.创建对象的几种方式 1.通过字面量创建 var obj = {}; 这种写法相当于: var obj = new Object(); 缺点:使用同一个接口创建很多单个对象,会产生大量重复代码 2. ...

  5. Unique Snowflakes UVA - 11572 (离散化+尺取法)

    Emily the entrepreneur has a cool business idea: packaging and selling snowflakes. She has devised a ...

  6. MySQL 深入浅出数据库索引原理(转)

    本文转自:https://www.cnblogs.com/aspwebchh/p/6652855.html 前段时间,公司一个新上线的网站出现页面响应速度缓慢的问题, 一位负责这个项目的但并不是搞技术 ...

  7. tomcat启动参数

    /usr/java/jdk1..0_191-amd64/bin/java -Djava.util.logging.config./conf/logging.properties -Djava.util ...

  8. CPU Cache 机制以及 Cache miss

    CPU体系结构之cache小结 1.What is cache? Cache是用来对内存数据的缓存. CPU要访问的数据在Cache中有缓存,称为“命中” (Hit),反之则称为“缺失” (Miss) ...

  9. IDEA 各版本在线激活(激活码)

    lan yu 大佬的授权又被封杀了,还好我收藏了一些其他的服务器地址. 在线授权服务器 https://jetlicense.nss.im/ 授权代码 K03CHKJCFT-eyJsaWNlbnNlS ...

  10. day 7-9 IO模型

    一,同步和异步,阻塞和非阻塞 同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就 ...