传送门


一个朴素的做法就是暴力连边并查集,可是这是\(O(n^2)\)的。发现每一次连边可以看成两个区间覆盖,这两个区间之间一一对应地连边。可线段树对应的两个节点的size可能不同,这会导致“一一对应”的条件在线段树上失效。所以我们需要使用ST表来完成连边。

对原序列建好ST表,对于每一个修改将两个区间覆盖到ST表上然后两两之间连边。注意在ST表上连边的两个区间要对应,即如果ST表上对应\([l,r]\)的区间与对应\([L,R]\)的区间连了边,意味着对于\(\forall i \in [0 , r - l],\)有边\((l + i , L + i)\)。

这样连边的复杂度是\(O(nlogn)\)的,但是查询就比较麻烦了,因为我们并查集只能查询大小为\(1\)的区间,而不能混入这些奇奇怪怪的区间。

但是我们可以把每一层ST表对应的并查集向下传,直到传到最底层。具体来说从上往下遍历每一层ST表对应的并查集,找到第\(i\)个点和它在这一层并查集上的根。这两个点在下一层的ST表中分别对应两个点,而连边的时候又是对应的,所以将它们的左儿子之间连边、右儿子之间连边即可。

总复杂度\(O(nlogn)\)

#include<iostream>
#include<cstdio>
#include<cctype>
#include<algorithm>
//This code is written by Itst
using namespace std; inline int read(){
int a = 0;
char c = getchar();
while(!isdigit(c))
c = getchar();
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return a;
} const int MAXN = 100007 , MOD = 1e9 + 7;
int ST[19][MAXN];
int N , M , cnt , logN , head[MAXN << 3] , dir[MAXN * 20] , fa[MAXN * 20]; void init(){
for(logN = 0 ; 1 << logN <= N ; ++logN)
for(int j = 1 ; j + (1 << logN) - 1 <= N ; ++j){
ST[logN][j] = ++cnt;
dir[cnt] = j;
fa[cnt] = cnt;
}
--logN;
} int find(int a){return fa[a] == a ? a : (fa[a] = find(fa[a]));} void merge(int a , int b){fa[find(a)] = find(b);} inline void add(int a , int b , int len){
for(int i = 18 ; i >= 0 ; --i)
if(len & (1 << i)){
merge(ST[i][a] , ST[i][b]);
a += 1 << i;
b += 1 << i;
}
} int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
//freopen("out","w",stdout);
#endif
N = read(); M = read();
init();
for(int i = 1 ; i <= M ; ++i){
int a = read() , b = read() , c = read();
read();
add(a , c , b - a + 1);
}
for(int i = logN ; i ; --i)
for(int j = 1 ; j + (1 << i) - 1 <= N ; ++j){
int t = find(ST[i][j]);
if(t != ST[i][j]){
int x = dir[t];
merge(ST[i - 1][j] , ST[i - 1][x]);
merge(ST[i - 1][j + (1 << i - 1)] , ST[i - 1][x + (1 << i - 1)]);
}
}
bool f = 0;
int ans = 1;
for(int i = 1 ; i <= N ; ++i)
if(fa[i] == i){
ans = ans * (9ll + f) % MOD;
f = 1;
}
cout << ans;
return 0;
}

LOJ2014 SCOI2016 萌萌哒 并查集、ST表优化连边的更多相关文章

  1. bzoj 4569 [Scoi2016]萌萌哒 并查集 + ST表

    题目链接 Description 一个长度为\(n\)的大数,用\(S_1S_2S_3...S_n\)表示,其中\(S_i\)表示数的第\(i\)位,\(S_1\)是数的最高位,告诉你一些限制条件,每 ...

  2. 洛谷P3295 萌萌哒 并查集 + ST表

    又切一道紫题!!! 成功的(看了一吨题解之后),我A掉了第二道紫题. 好,我们仔细观察,发现这是一个排列组合问题. 有些限定条件,要相等的地方,我们就用并查集并起来.最后一查有多少个并查集,就有多少个 ...

  3. luogu3295 萌萌哒 (并查集+ST表)

    如果给相同的位置连边,最后联通块数是n,最后答案就是$9*10^{n-1}$ 但直接连边是$O(n^2)$的 所以事先处理出一个ST表,每次O(1)地给那个ST表连边 最后再一点一点下放,就是把在这层 ...

  4. [BZOJ4569] [Luogu 3295] [SCOI2016]萌萌哒(并查集+倍增)

    [BZOJ4569] [Luogu 3295] [SCOI2016]萌萌哒(并查集+倍增) 题面 有一个n位的十进制数a(无前导0),给出m条限制,每条限制\((l_1,r_1,l_2,r_2)(保证 ...

  5. 2018.09.25 codeforces1053E. Euler tour(并查集+st表+模拟)

    传送门 毒瘤细节题. 首先考虑不合法的情况. 先把相同的值配对,这样就构成了一些区间. 那么如果这些区间有相交的话,就不合法了. 如何判断?DZYO安利了一波st表,我觉得很不错. 接着考虑两个相同的 ...

  6. Luogu P3295 [SCOI2016]萌萌哒(并查集+倍增)

    P3295 [SCOI2016]萌萌哒 题面 题目描述 一个长度为 \(n\) 的大数,用 \(S_1S_2S_3 \cdots S_n\) 表示,其中 \(S_i\) 表示数的第 \(i\) 位, ...

  7. [bzoj4569][SCOI2016]萌萌哒-并查集+倍增

    Brief Description 一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条 件表示为四个数,l1,r1,l2,r2,即两 ...

  8. 洛谷 3295 [SCOI2016]萌萌哒——并查集优化连边

    题目:https://www.luogu.org/problemnew/show/P3295 当要连的边形如 “一段区间内都是 i 向 i+L 连边” 的时候,用并查集优化连边. 在连边的时候,如果要 ...

  9. BZOJ 4569: [Scoi2016]萌萌哒 [并查集 倍增]

    传送门 题意:长为$n \le 10^5$的数字,给出$m \le 10^5$个限制$[l1,r1]\ [l2,r2]$两个子串完全相等,求方案数 把所有要求相等的位置连起来,不就是$9*10^{连通 ...

随机推荐

  1. UnrealEd3视图导航及常用快捷键

    本博客使用的版本:2010-08   [更多其他的UE3版本][tps所用版本: 2011-02]     [最新的UE3版本 -- 2015-02] [unreal engine wiki  中文w ...

  2. [20170604]12c Top Frequency histogram补充.txt

    [20170604]12c Top Frequency histogram补充.txt 1.环境:SCOTT@test01p> @ ver1PORT_STRING                 ...

  3. c/c++ 用普利姆(prim)算法构造最小生成树

    c/c++ 用普利姆(prim)算法构造最小生成树 最小生成树(Minimum Cost Spanning Tree)的概念: ​ 假设要在n个城市之间建立公路,则连通n个城市只需要n-1条线路.这时 ...

  4. fedora 29 桌面版 设置 cockpit 自动开机启动

    systemctl enable cockpit 时,会出现如下错误: The unit files have no installation config (WantedBy, RequiredBy ...

  5. xshell的一些常用配置

    1  在xshell中鼠标滚轮和右键的快捷方式 利用鼠标滚轮和右键快速粘贴上面复制的内容 打开xshell的工具---选项-----键盘和鼠标 点击确定 回到xshell即可使用

  6. 转载:java中Thread.sleep()函数使用

    点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...

  7. JDBC复习2

    前面复习了一些基础知识以及如何抽取一些常用的代码,接下来就结合junit4做一个增删改查的小demo 重点是这么几个步骤:1.创建连接 2.编写sql语句 3.编写sql语句的载体 4.如果是Prep ...

  8. 微信小程序多层嵌套循环,二级数组遍历

    小程序中的遍历循环类似于angularJS的遍历. 二级数组遍历有一个坑.二级遍历wx:for循环的时候,需要注意.(代码如下) JS代码: data: { groups: [ [ { title: ...

  9. MySQL高级知识(五)——索引分析

    前言:前面已经学习了explain(执行计划)的相关知识,这里利用explain对索引进行优化分析. 0.准备 首先创建三张表:tb_emp(职工表).tb_dept(部门表)和tb_desc(描述表 ...

  10. Spring将Bean导入IOC容器

    @Import 注解可以普通类导入到 IoC容器中. 想要让一个普通类接受 Spring 容器管理,有以下方法 使用 @Bean 注解 使用 @Controller @Service @Reposit ...