P3295 [SCOI2016]萌萌哒

题面

题目描述

一个长度为 \(n\) 的大数,用 \(S_1S_2S_3 \cdots S_n\) 表示,其中 \(S_i\) 表示数的第 \(i\) 位, \(S_1\) 是数的最高位。告诉你一些限制条件,每个条件表示为四个数, \(l_1,r_1,l_2,r_2\) ,即两个长度相同的区间,表示子串 \(S_{l_1}S_{l_1+1}S_{l_1+2} \cdots S_{r_1}\) 与 \(S_{l_2}S_{l_2+1}S_{l_2+2} \cdots S_{r_2}S\) 完全相同。

比如 \(n=6\) 时,某限制条件 \(l_1=1,r_1=3,l_2=4,r_2=6\) ,那么 \(123123\) , \(351351\) 均满足条件,但是 \(12012\) , \(131141\) 不满足条件,前者数的长度不为 \(6\) ,后者第二位与第五位不同。问满足以上所有条件的数有多少个。

输入输出格式

输入格式:

第一行两个数 \(n\) 和 \(m\) ,分别表示大数的长度,以及限制条件的个数。

接下来 \(m\) 行,对于第 \(i\) 行,有 \(4\) 个数 \(l_{i1},r_{i1},l_{i2},r_{i2}\) ,分别表示该限制条件对应的两个区间。

\(1\le n\le 10^5\) , \(1\le m\le 10^5\) , \(1\le l_{i1},r_{i1},l_{i2},r_{i2} \le n\) ;并且保证 \(r_{i1}-l_{i1}=r_{i2}-l_{i2}\) 。

输出格式:

一个数,表示满足所有条件且长度为n的大数的个数,答案可能很大,因此输出答案模 \(10^9+7\) 的结果即可。

输入输出样例

输入样例:

4 2
1 2 3 4
3 3 3 3

输出样例:

90

思路

首先想到一个 \(O(m \times n^2)\) 的 优秀 做法:对于每一位相同的数字,我们可以把它加进一个相同的并查集中,然后就可以按照并查集的个数进行统计。例如,假设右 \(R\) 个并查集,那么:

\[ans=10^{R-1} \times 9
\]

这是因为,每一位上的数字都可在 \([0,9]\) 这个区间的十个数中选择,而不能有前导零。

再考虑倍增优化。我们可以把每个区间按照二进制拆分,倍增处理,把每一块加入同一个并查集中。统计答案时先下传并查集到底(有点像线段树的 \(pushdown\) 操作),最后再对每个长度为 \(2^0=1\) 的区间进行答案统计,得到最终答案,总时间复杂度为 \(O(m \times n \log ^2n)\) 。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL P=1e9+7;
LL n,m,ans,fa[20][100005];
bool flag;
inline LL read()
{
LL re=0;
char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
return re;
}
inline LL fd(LL x,LL y)
{
LL r=x;
while(fa[y][r]!=r) r=fa[y][r];
LL i=x,j;
while(i!=r) j=fa[y][i],fa[y][i]=r,i=j;
return r;
}
inline void merge(LL x,LL y,LL z)
{
LL fx=fd(x,z),fy=fd(y,z);
if(fx!=fy) fa[z][fx]=fa[z][fy];
}
int main()
{
n=read(),m=read();
for(LL i=0;i<=17;i++)
for(LL j=1;j<=n;j++)
fa[i][j]=j;
while(m--)
{
LL l1=read(),r1=read(),l2=read(),r2=read();
for(LL i=17;i>=0;i--)
if(l1+(1<<i)-1<=r1)
{
merge(l1,l2,i);
l1+=(1<<i),l2+=(1<<i);
}
}
for(LL i=17;i;i--)
for(LL j=1;j+(1<<i)-1<=n;j++)
{
merge(j,fd(j,i),i-1);
merge(j+(1<<(i-1)),fa[i][j]+(1<<(i-1)),i-1);
}
for(LL i=1;i<=n;i++) if(fd(i,0)==i) ans=flag?ans*10%P:9,flag=true;
printf("%lld",ans);
return 0;
}

Luogu P3295 [SCOI2016]萌萌哒(并查集+倍增)的更多相关文章

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

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

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

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

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

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

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

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

  5. LOJ2014 SCOI2016 萌萌哒 并查集、ST表优化连边

    传送门 一个朴素的做法就是暴力连边并查集,可是这是\(O(n^2)\)的.发现每一次连边可以看成两个区间覆盖,这两个区间之间一一对应地连边.可线段树对应的两个节点的size可能不同,这会导致" ...

  6. luogu P3295 [SCOI2016]萌萌哒

    传送门 题目条件"两个子串\(S[l_1,r_1],S[l_2,r_2]\)完全相同"等价于\(\forall i \in[0,r_1-l_1+1],S_{l1+i}=S_{l_2 ...

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

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

  8. 洛谷P3295 [SCOI2016]萌萌哒 题解

    洛谷P3295 [SCOI2016]萌萌哒 题目描述 公式粘过来就乱了,还是去洛谷看题吧 分析 如果暴力解决的话就是使用并查集把位数相同的数位并在一起.比如区间[1,2]和区间[3,4]的数字完全相同 ...

  9. 洛谷P3295 [SCOI2016]萌萌哒(倍增+并查集)

    传送门 思路太妙了啊…… 容易才怪想到暴力,把区间内的每一个数字用并查集维护相等,然后设最后总共有$k$个并查集,那么答案就是$9*10^{k-1}$(因为第一位不能为0) 考虑倍增.我们设$f[i] ...

随机推荐

  1. 1.2python基础_数字类型_数字(Number)类型

    一.整型(int型.整数) 整型 等价于C中的有符号长整型(long) 与系统的最大整型一致(如32位机器上的整型是32位,64位机器上的整型是64位), 可以表示的整数范围在[-sys.maxint ...

  2. SQL Serve 临时表

    SQL Server 支持临时表.临时表就是那些名称以井号 (#) 开头的表.如果当用户断开连接时没有除去临时表,SQL Server 将自动除去临时表.临时表不存储在当前数据库内,而是存储在系统数据 ...

  3. TIB、TEB 信息

    https://en.wikipedia.org/wiki/Win32_Thread_Information_Block 这是重点 Position Length Windows Versions D ...

  4. java_递归

    递归:方法在有结束条件的情况下调用自己本身 public static void main(String[] args) { int i = shu01(5); System.out.println( ...

  5. 在页面上显示PDF

    /// <summary> /// 读取PDF文件 /// </summary> /// <param name="fName">文件名称(可以 ...

  6. JS规则 我还有其它用途( +号操作符)例如,算术操作符(+、-、*、/等),比较操作符(<、>、>=、<=等),逻辑操作符(&&、||、!)

    我还有其它用途( +号操作符) 操作符是用于在JavaScript中指定一定动作的符号. (1)操作符 看下面这段JavaScript代码. sum = numa + numb; 其中的"= ...

  7. php socket模拟http中post或get提交数据

    php socket模拟http中post或者get提交数据的示例代码. 代码: sock_post.php: <?php /** * php socket模拟post\get请求 * 编辑:脚 ...

  8. CNN网络中的不变性理解

    神经网络中的不变性 原文:https://blog.csdn.net/voxel_grid/article/details/79275637     个人认为cnn中conv层对应的是“等变性”(Eq ...

  9. Android开发 音视频开发需要了解的专业术语知识

    前言 在摸索一段时间的音视频开发后,越来越发现这个坑的深度真是特别的深. 除了了解Android自带的音视频处理API以外,还得了解一些视频与音频方面的知识.这篇博客就是主要讲解这方面的专业术语.内容 ...

  10. Ubuntu 18.04 Linux上安装Etherpad,基于Web的实时协作编辑器

    介绍 Etherpad是一个开源的,基于Web的实时协作编辑器(http://www.0834nanke.com) 它允许多个人使用他们的Web浏览器同时编辑文档. 它还提供了一些很酷的功能,如富文本 ...