http://uoj.ac/problem/356

题解

思路和\(NOIP\)双栈排序差不多。

对于两个元素,若\(l_1<l_2<r_1<r_2\)那么它们不能在一个栈里,我们连一条边。

若最后的这张图是二分图,那么答案就是\(2^{联通块个数}\)。

这道题就是要我们优化连边。

我们把所有线段按照左端点排序,然后我们用平衡树按照右端点为关键字维护已经扫描过去的线段。

发现要和当前扫描到的线段连边的是平衡树上\(dfs\)序连续的一段区间。

考虑这个边怎么连。

我们只需要在这个区间的右端点处和这个点连上1的边,中间连0边就行了。

所以我们可以用并查集的思想,只和右端点连边,在维护一个连0边的\(set\),如果一个点和两边都连上0边就删掉它。

代码

#include<bits/stdc++.h>
#define N 2000009
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inf=1e9;
int pre[N],nxt[N],head[N],tot;
int top,st[N];
int n;
int vis[N];
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
inline void MOD(int &x){x=x>=mod?x-mod:x;}
inline ll power(ll x,ll y){
ll ans=1;
while(y){
if(y&1)ans=ans*x%mod;
x=x*x%mod;y>>=1;
}
return ans;
}
struct edge{
int n,to,l;
}e[N*6];
inline void add(int u,int v,int l){
if(!u||!v)return;
// cout<<u<<" "<<v<<" "<<l<<endl;
e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;
e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=l;
}
struct node{
int l,r;
inline bool operator <(const node &b)const{
if(l!=b.l)return l<b.l;
return r<b.r;
}
}a[N];
struct nd{
int pos,id;
inline bool operator <(const nd &b)const{
return pos<b.pos;
}
};
set<nd>s1,s2;
set<nd>::iterator it;
void dfs(int u){
for(int i=head[u];i;i=e[i].n){
int v=e[i].to;
if(vis[v]&&(vis[u]^e[i].l)!=vis[v]){puts("0");exit(0);}
if(!vis[v]){
vis[v]=vis[u]^e[i].l;
dfs(v);
}
}
}
int main(){
n=rd();
for(int i=1;i<=n;++i)a[i].l=rd(),a[i].r=rd();
sort(a+1,a+n+1);
s1.insert(nd{-inf,0});s1.insert(nd{inf,0});
s2.insert(nd{-inf,0});s2.insert(nd{inf,0});
for(int i=1;i<=n;++i){
it=s1.lower_bound(nd{a[i].r,i});
nxt[i]=it->id;
pre[it->id]=0;
it--;
pre[i]=it->id;
nxt[it->id]=0;
if(it->pos>a[i].l)add(i,it->id,1);
it=s2.lower_bound(nd{a[i].r,i});--it;
while(1){
if(it->pos<a[i].l)break;
if(pre[it->id]&&a[pre[it->id]].r>a[i].l){add(it->id,pre[it->id],0);pre[it->id]=0;}
if(nxt[it->id]&&a[nxt[it->id]].r<a[i].r){add(it->id,nxt[it->id],0);nxt[it->id]=0;}
if(!pre[it->id]&&!nxt[it->id])st[++top]=it->id;
it--;
}
for(int j=1;j<=top;++j)s2.erase(nd{a[st[j]].r,st[j]});
top=0;
s1.insert(nd{a[i].r,i});
s2.insert(nd{a[i].r,i});
}
int ans=1;
for(int i=1;i<=n;++i)if(!vis[i]){
vis[i]=2;
dfs(i);
MOD(ans=ans+ans);
}
printf("%d\n",ans);
return 0;
}

【JOI2017春季合宿】Port Facility的更多相关文章

  1. UOJ356 [JOI2017春季合宿] Port Facility 【启发式合并】【堆】【并查集】

    题目分析: 好像跑得很快,似乎我是第一个启发式合并的. 把玩具看成区间.首先很显然如果有两个玩具的进出时间有$l1<l2<r1<r2$的关系,那么这两个玩具一定在不同的栈中间. 现在 ...

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

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

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

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

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

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

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

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

  6. JOI2017 春季合宿:Railway Trip

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

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

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

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

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

  9. LOJ #2731 [JOI2016春季合宿]Solitaire (DP、组合计数)

    题目链接 https://loj.ac/problem/2731 题解 首先一个很自然的思路是,设\(dp[i][j]\)表示选了前\(i\)列,第\(2\)行第\(i\)列的格子是第\(j\)个被填 ...

随机推荐

  1. 小解POJO、PO、BO、VO

    POJO :plain ordinary java object 无规则简单java对象 一个中间对象,可以转化为PO.DTO.VO. 一个简单的Java类,这个类没有实现/继承任何特殊的java接口 ...

  2. PHP_OS的常见值

    PHP_OS是PHP中的一个预定义常量,表示当前操作系统.那么PHP_OS有哪些值可用呢??PHP_OS的值一般可以为:CYGWIN_NT-5.1,Darwin,FreeBSD,HP-UX,IRIX6 ...

  3. shell script简单笔记

    变量 shell script是一种脚本语言,变量的定义是通过 myName=HYB 这样的形式定义的. 当存在空格时,可以通过双引号或单引号将其变为字符串.双引号不进行转义,单引号将内容进行转义为一 ...

  4. Python 矩阵(线性代数)

    Python 矩阵(线性代数) 这里有一份新手友好的线性代数笔记,是和深度学习花书配套,还被Ian Goodfellow老师翻了牌. 笔记来自巴黎高等师范学院的博士生Hadrien Jean,是针对& ...

  5. vscode配置汇总

    一.ESlint插件的作用:格式化代码 二.vetur插件:

  6. GitHub入门使用

    1.首先注册账号. 2.新建仓库. 3.安装GitBash 4.首先要在本地创建一个ssh key. $ ssh -keygen -t rsa -C "your email@.com&quo ...

  7. Linux文档整理之【Nginx安装Docker】

    这次整理的文档是Docker安装 先说明下我用的系统是Linux Centos,不同的Linux版本差别不大. 1.安装依赖包 sudo yum install -y yum-utils device ...

  8. vscode调试php

    xdebug调试vscode 下载xdebug.dll扩展库 php.ini配置 [XDebug] xdebug.remote_enable = xdebug.remote_autostart = z ...

  9. Linux学习--第三天--linux文件目录、ls、mkdir、mv、rm、touch、cat、tac、more、less、head、tail、ln、chmod、chown、chgrp、umask

    文件目录 目录名 备注 bin 下面的命令所有人都可以运行 sbin 只有root才能运行,s代表super /mnt,/media,/misc 都是挂载目录,但一般只用mnt /opt 第三方软件安 ...

  10. ubuntu16.04下docker安装和简单使用(转)

    ubuntu16.04下docker安装和简单使用   转自:https://www.cnblogs.com/hupeng1234/p/9773770.html 前提条件 操作系统 docker-ce ...