首页 > 其他分享 >「JOISC 2017 Day 1」港口设施

「JOISC 2017 Day 1」港口设施

时间:2022-10-18 19:44:12浏览次数:60  
标签:return int void col JOISC MAXN read 2017 Day

link

Solution

可以看出对于两个点 \((a,b),(c,d)\),如果存在 \(a<c<b<d\),那么两者就不能在同一个栈。所以我们可以把这种关系连边,无解即是存在奇环,否则答案就是 \(2\) 的连通块个树次方。

似乎可以直接动态开点线段树优化建图?但是还有一种比较优美的做法。

考虑如何优化连边。我们按 \(b_i\) 排序之后加进去,每一次考虑到 \((a_i,b_i)\) 即是往未被加进去且左端点在 \((a_i,b_i)\) 的点进行连边。但是这样边数还是很大。

我们可以发现的是,对于这个区间的点,它们的颜色应该是一样的,而颜色一样的我们显然可以并起来往其中一个点连边即可,所以我们可以考虑并查集维护一个点最远的同颜色段。加没加入也可以用并查集进行维护。

复杂度显然是 \(\Theta(n\log n)\) 的。

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define mod 1000000007
#define MAXN 2000005

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}

int n,m,a[MAXN],b[MAXN],ql[MAXN],fa[MAXN],nxt[MAXN],col[MAXN];
int findSet (int x){return fa[x] == x ? x : fa[x] = findSet (fa[x]);}

vector <int> H[MAXN];
void linkit (int u,int v){H[u].push_back (v),H[v].push_back (u);}

bool dfs (int u,int c){
	if (col[u] != -1 && col[u] != c) return 0;
	if (col[u] != -1) return 1;
	col[u] = c;
	for (Int v : H[u]) if (!dfs (v,c ^ 1)) return 0;
	return 1;
}

signed main(){
	read (n);
	for (Int i = 1,x,y;i <= n;++ i) read (x,y),b[x] = b[y] = i;
	for (Int x = 1;x <= n * 2;++ x) fa[x] = nxt[x] = x;
	for (Int i = 1;i <= 2 * n;++ i){
		int t = b[i];
		if (!ql[t]){a[++ m] = t,ql[t] = m;continue;}
		for (Int j = fa[ql[t]] = findSet (ql[t] + 1);j <= m;){
			linkit (a[j],t);
			int u = findSet (nxt[j] + 1);
			nxt[j] = m,j = u;
		}
	}
	memset (col,-1,sizeof (col));
	int tot = 0,ans = 1;
	for (Int x = 1;x <= n;++ x) if (col[x] == -1){
		if (!dfs (x,0)) return puts ("0") & 0;
		else tot ++;
	}
	for (Int i = 1;i <= tot;++ i) ans = ans * 2 % mod;
	write (ans),putchar ('\n');
	return 0;
}

标签:return,int,void,col,JOISC,MAXN,read,2017,Day
From: https://www.cnblogs.com/Dark-Romance/p/16803825.html

相关文章

  • 代码随想录day21
    530.二叉搜索树的最小绝对差解题步骤:1、将二叉搜索树转化为有序数组;2、按照重新排序后的数组进行遍历,获取最小的绝对值差。1classSolution{2private:3......
  • 进入python的世界_day17_python基础——了解模块、如何使用和导入模块、包的原理
    一、模块介绍1.什么是模块​ 其实我们前一阵已经接触过了,importxxx、fromxximportxxx​ 能够有一定功能的集合体就是模块,比如有某些功能的py文件,包含这个文件的......
  • day17模块基础简介
    目录索引取值与迭代取值的差异模块简介模块的分类导入模块的两种句式导入模块补充说明循环导入问题判断文件类型模块的查找顺序绝对导入与相对导入包索引取值与迭代取值的......
  • 《剑指offer》day13
    调整数组顺序使奇数位于偶数前面题目描述思路双指针代码实现双指针classSolution{publicstaticvoidmain(String[]args){int[]nums={1,2,3,4......
  • java_day14
    Java基础Java集合框架泛型本质是参数化类型,把类型作为参数传递常见类型有泛型类、泛型接口、泛型方法好处:提高代码的重用性、防止类型转换异常​ 泛型类/***......
  • 学习python-Day75
    运维的本质运维:运行维护应用程序岗位需求:自动化运维、DBA、docker+K8s...运维职责:尽可能保证应用程序24小时不间断运行尽可能保证数据的安全尽可能提升程序的......
  • 代码随想录Day4
    LeetCode349: 给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序.  思路:需要在输出......
  • 【算法训练营day6】LeetCode242. 有效的字母异位词 LeetCode349. 两个数组的交集 Leet
    【算法训练营day6】LeetCode242.有效的字母异位词LeetCode349.两个数组的交集LeetCode202.快乐数LeetCode1.两数之和LeetCode242.有效的字母异位词题目链接:242.......
  • 【leetcode_C语言_链表_day3】203.移除链表元素 &&707.设计链表 &&206.反转链表
    203.移除链表元素1.题目给你一个链表的头节点head和一个整数val,请你删除链表中所有满足Node.val==val的节点,并返回新的头节点。示例1:​输入:he......
  • day49-JDBC和连接池05
    JDBC和连接池0511.BasicDAO先来分析一个问题前面我们使用了Apache-DBUtils和Druid简化了JDBC开发,但仍存在以下不足:SQL语句是固定的,不能通过参数传入,通用性不好,需要......