题面

点此看题

题意很明白,就不转述了吧。

题解

题目相当于告诉了我们若干等量关系,每个限制

l

1

,

r

1

,

l

2

,

r

2

\tt l_1,r_1,l_2,r_2

l1​,r1​,l2​,r2​ 相当于

S

l

1

=

S

l

2

,

S

l

1

+

1

=

S

l

2

+

1

,

,

S

r

1

=

S

r

2

\tt S_{l_1}=S_{l_2},S_{l_1+1}=S_{l_2+1},\dots,S_{r_1}=S_{r_2}

Sl1​​=Sl2​​,Sl1​+1​=Sl2​+1​,…,Sr1​​=Sr2​​ 这

r

1

l

1

+

1

r_1-l_1+1

r1​−l1​+1 个等量关系,每个等量关系把两个点绑在了一起。用并查集,把相等的点并起来,最终每个连通块内值相等,不同的块两两独立。

这样建边无疑是

n

2

\tt n^2

n2 级别的,远不能通过。但,一个有趣的现象是,最终实际存在在并查集中的边最多只有

n

1

\tt n-1

n−1 条。别的边到哪里去了呢?别的边的确没用,因此,如果能够尽量舍弃掉没用的边,那么解决这题就不在话下。

问题是,我们是不能提前知道每一条边是不是废边的。但同时,我们知道,经过并查集的算法过程,它会自然地并且神奇地把有用的边都给你留下来。

于是就有了这么一个做法:慢节奏合并并查集,过程中充分利用并查集筛选边的性质。

我们先用倍增思想,把每个限制

{

l

1

,

r

1

,

l

2

,

r

2

}

\tt \{l_1,r_1,l_2,r_2\}

{l1​,r1​,l2​,r2​} 变成两个长度为

2

k

\tt2^k

2k(选取使其不超过

[

l

1

,

r

1

]

\tt[l_1,r_1]

[l1​,r1​] 的长度并且最大化的

k

\tt k

k) 的限制:

{

l

1

,

r

1

,

l

1

+

2

k

1

,

r

1

+

2

k

1

}

\tt\{l_1,r_1,l_1+2^k-1,r_1+2^k-1\}

{l1​,r1​,l1​+2k−1,r1​+2k−1} 和

{

l

2

2

k

+

1

,

r

2

2

k

+

1

,

l

2

,

r

2

}

\tt\{l_2-2^k+1,r_2-2^k+1,l_2,r_2\}

{l2​−2k+1,r2​−2k+1,l2​,r2​} ,虽然有重,但是不影响。接着,把它们都放在限制集

b

u

[

k

]

\tt bu[k]

bu[k] 里待命。

然后,从大到小枚举

k

\tt k

k (

k

log

n

\tt k\leq\log n

k≤logn)。每次,我们假定每个序列中的点

i

\tt i

i 代表着

[

i

,

i

+

2

k

1

]

\tt[i,i+2^k-1]

[i,i+2k−1] 这个大数区间,读取

b

u

[

k

]

\tt bu[k]

bu[k] 里每个元素

{

x

,

y

,

x

+

2

k

1

,

y

+

2

k

1

}

\tt\{x,y,x+2^k-1,y+2^k-1\}

{x,y,x+2k−1,y+2k−1} ,将点

x

\tt x

x 和点

y

\tt y

y 在并查集里合并,也就是意味着

[

x

,

x

+

2

k

1

]

\tt[x,x+2^k-1]

[x,x+2k−1] 和

[

y

,

y

+

2

k

1

]

\tt[y,y+2^k-1]

[y,y+2k−1] 两个区间的大数都对应相等。

在枚举到

k

\tt k'

k′ 之前,并查集里已经有的边,就是精简后的了。一开始,并查集里形如

(

x

,

y

)

\tt(x,y)

(x,y) 的边还代表着

[

x

,

x

+

2

k

+

1

1

]

\tt[x,x+2^{k'+1}-1]

[x,x+2k′+1−1] 和

[

y

,

y

+

2

k

1

1

]

\tt[y,y+2^{k'-1}-1]

[y,y+2k′−1−1] 相等,到这一层,就得代表

[

x

,

x

+

2

k

1

]

\tt[x,x+2^{k'}-1]

[x,x+2k′−1] 和

[

y

,

y

+

2

k

1

]

\tt[y,y+2^{k'}-1]

[y,y+2k′−1] 相等了,因此我们把它分裂为两条边

(

x

,

y

)

\tt(x,y)

(x,y) 和

(

x

+

2

k

,

y

+

2

k

)

\tt(x+2^{k'},y+2^{k'})

(x+2k′,y+2k′) ,再把多出的这条

(

x

+

2

k

,

y

+

2

k

)

\tt(x+2^{k'},y+2^{k'})

(x+2k′,y+2k′) 连到并查集里。

这样一来,一开始加的边是

O

(

n

)

\tt O(n)

O(n) 级别的,枚举时每一层加的边也是

O

(

n

)

\tt O(n)

O(n) 级别的,保留下来的边还是小于等于

n

1

\tt n-1

n−1 条。总共加的边最多就

n

log

n

\tt n\log n

nlogn 条,优化得非常到位。

这么个巧妙的做法,不知道当初第一个 AC 的人是怎么想出来的。这估计算是怎样解题里面说的U

n

b

e

l

i

e

v

a

b

l

e

!

\tt Unbelievable!

Unbelievable!一类题吧。

CODE

巧妙的做法往往代码简单。

#include<set>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
const int MOD = 1000000007;
int n,m,i,j,s,o,k;
struct it{
int l,r;it(){l=r=0;}
it(int L,int R){l=L;r=R;}
};
vector<it> bu[105];
int fa[MAXN];
int findf(int x) {return fa[x] == x ? x:(fa[x] = findf(fa[x]));}
void unionSet(int a,int b) {
int u = findf(a),v = findf(b);
if(u > v) swap(u,v);
fa[u] = v; return ;
}
bool ct[MAXN];
int main() {
n = read();m = read();
for(int i = 1;i <= n;i ++) {
fa[i] = i;
}
for(int i = 1;i <= m;i ++) {
s = read();int le = read() - s + 1;
o = read(); read();
int l2 = 0;
for(int j = 0;(1<<j) <= le;j ++) l2 = j;
bu[l2].push_back(it(s,o));
bu[l2].push_back(it(s+le-(1<<l2),o+le-(1<<l2)));
}
for(int i = 20;i >= 0;i --) {
for(int j = n;j > 0;j --) {
if(findf(j) != j) {
int k = findf(j);
if(k+(1<<i) <= n)
bu[i].push_back(it(j+(1<<i),k+(1<<i)));
}
}
for(int j = 0;j < (int)bu[i].size();j ++) {
s = bu[i][j].l,o = bu[i][j].r;
unionSet(s,o);
}
}
int ans = 1;
for(int i = 1;i <= n;i ++) {
if(!ct[findf(i)]) {
ct[findf(i)] = 1;
if(i == 1) ans = ans *9ll % MOD;
else ans = ans *10ll % MOD;
}
}
printf("%d\n",ans);
return 0;
}

LOJ#2014「SCOI2016」萌萌哒(倍增,并查集优化连边)的更多相关文章

  1. 【LOJ】#2014. 「SCOI2016」萌萌哒

    题解 这个题好妙啊 首先我们发现,如果我们可以暴力,就是把相同的元素拿并查集合起来,最后统计集合个数\(cnt\) 答案是\(9\*10^{cnt - 1}\) 然而我们做不到= = 我们可以用倍增的 ...

  2. 「SCOI2016」萌萌哒 解题报告

    「SCOI2016」萌萌哒 这思路厉害啊.. 容易发现有个暴力是并查集 然后我想了半天线段树优化无果 然后正解是倍增优化并查集 有这个思路就简单了,就是开一个并查集代表每个开头\(i\)每个长\(2^ ...

  3. loj#2013. 「SCOI2016」幸运数字 点分治/线性基

    题目链接 loj#2013. 「SCOI2016」幸运数字 题解 和树上路径有管...点分治吧 把询问挂到点上 求出重心后,求出重心到每个点路径上的数的线性基 对于重心为lca的合并寻味,否则标记下传 ...

  4. loj#2015. 「SCOI2016」妖怪 凸函数/三分

    题目链接 loj#2015. 「SCOI2016」妖怪 题解 对于每一项展开 的到\(atk+\frac{dnf}{b}a + dnf + \frac{atk}{a} b\) 令$T = \frac{ ...

  5. loj#2016. 「SCOI2016」美味

    题目链接 loj#2016. 「SCOI2016」美味 题解 对于不带x的怎么做....可持久化trie树 对于带x,和trie树一样贪心 对于答案的二进制位,从高往低位贪心, 二进制可以表示所有的数 ...

  6. loj#2012. 「SCOI2016」背单词

    题目链接 loj#2012. 「SCOI2016」背单词 题解 题面描述有点不清楚. 考虑贪心 type1的花费一定不会是优的,不考虑, 所以先把后缀填进去,对于反串建trie树, 先填父亲再填儿子, ...

  7. 「SCOI2016」萌萌哒

    「SCOI2016」萌萌哒 题目描述 一个长度为 \(n\) 的大数,用 \(S_1S_2S_3 \ldots S_n\) 表示,其中 \(S_i\) 表示数的第 \(i\) 位,\(S_1\) 是数 ...

  8. loj #2013. 「SCOI2016」幸运数字

    #2013. 「SCOI2016」幸运数字 题目描述 A 国共有 n nn 座城市,这些城市由 n−1 n - 1n−1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以 ...

  9. 【BZOJ4569】[Scoi2016]萌萌哒 倍增+并查集

    [BZOJ4569][Scoi2016]萌萌哒 Description 一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条件表示为四 ...

随机推荐

  1. c++ FHQ Treap

    前面我们对平衡树有了个大概的了解 关于 Treap Treap=Binary Search Tree + Heap 二叉搜索树 + 二叉堆(一般是小根堆) Treap 每一个节点有两个值 一个值是平衡 ...

  2. 全新升级的AOP框架Dora.Interception[3]: 基于特性标注的拦截器注册方式

    在Dora.Interception(github地址,觉得不错不妨给一颗星)中按照约定方式定义的拦截器可以采用多种方式注册到目标方法上.本篇文章介绍最常用的基于"特性标注"的拦截 ...

  3. Nodejs实现图片的上传、压缩预览、定时删除

    前言 我们程序员日常都会用到图片压缩,面对这么常用的功能,肯定要尝试实现一番.第一步,node基本配置 这里我们用到的是koa框架,它可是继express框架之后又一个更富有表现力.更健壮的web框架 ...

  4. WPF开发随笔收录-自定义图标控件

    一.前言 1.在以前自学的过程中,软件需要使用到图标的时候,总是第一个想法是下载一个图片来充当图标使用,但实际得出来的效果会出现模糊的现象.后来网上学习了字体图标库的用法,可以在阿里云矢量图网站那里将 ...

  5. wcf .net webService和 .net webApi的联系与差异

    首先,我们需要清楚它们的概念,然后才能走好下一步. wcf是对于ASMX,.Net Remoting,Enterprise Service,WSE,MSMQ等技术的整合,它是一种重量级消息交互框架,广 ...

  6. 聊聊 RPA 方向的规划:简单有价值的事情长期坚持做

    「简单有价值的事情长期坚持做」 这是成功最简单,但也最难学的秘诀.不经过训练,人很难意识到时间复利的威力. 仙剑奇侠传的「十里坡剑神」和金庸群侠传的「十级野球拳」,就是简单的事情持之以恒反复做,最后就 ...

  7. 令你瞠目结舌的 Python 代码技巧

    0. for-else 在 Python 中,else 不仅可以与 if 搭配使用,还可以与 for 结合. python答疑 咨询 学习交流群2:660193417### for x in rang ...

  8. 关于NAND FLASH解扣的认识

    NAND FLASH是现在非常重要的存储介质,根据出厂时厂家检测结果可分为原片(正片).白片和黑片. 所谓原片就是NAND FLASH生产厂商挑选出来的最好的晶圆,切割下来经过了各项测试之后封装成成品 ...

  9. Elasticsearch面试题

    Elasticsearch面试题 1.Elasticsearch是如何实现master选举的? 1.对所有可以成为master的节点根据nodeId排序,每次选举每个节点都把自己所知道节点排一次序,然 ...

  10. 数据孤岛下的新破局 Real Time DaaS:面向 AP+TP 业务的数据平台架构

    从传统数仓,到大数据平台,再到数据中台和湖仓一体新数据平台,在日益加重的数据孤岛困扰下,面向AP场景的解决方案可谓浩如烟海.但实际上,企业在TP类型业务上的投入和AP的比率却高达9:1,为什么没有为T ...