[bzoj4569] [loj#2014] [Scoi2016] 萌萌哒
Description
一个长度为 \(n\) 的大数,用 \(S1S2S3...Sn\) 表示,其中 \(Si\) 表示数的第 \(i\) 位, \(S1\) 是数的最高位,告诉你一些限制条件,每个条件表示为四个数,\(l1\),\(r1\),\(l2\),\(r2\),即两个长度相同的区间,表示子串 \(Sl1\) \(Sl1+1\) \(Sl1+2\) \(...\) \(Sr1\) 与 \(Sl2\) \(Sl2+1\) \(Sl2+2\) \(...\) \(Sr2\) 完全相同。比如 \(n=6\) 时,某限制条件 \(l1=1\),\(r1=3\),\(l2=4\),\(r2=6\) ,那么123123,351351均满足条件,但是12012,131141不满足条件,前者数的长度不为6,后者第二位与第五位不同。问满足以上所有条件的数有多少个。
Input
第一行两个数 \(n\) 和 \(m\) ,分别表示大数的长度,以及限制条件的个数。接下来 \(m\) 行,对于第 \(i\) 行,有 4 个数 \(li1\),\(ri1\),\(li2\),\(ri2\) ,分别表示该限制条件对应的两个区间。
\(1 \leq n \leq 10^5\),\(1 \leq m \leq 10^5\),\(1 \leq li1,ri1,li2,ri2 \leq n\);并且保证 \(ri1-li1=ri2-li2\) 。
Output
一个数,表示满足所有条件且长度为 \(n\) 的大数的个数,答案可能很大,因此输出答案模 \(10^9+7\) 的结果即可。
Sample Input
4 2
1 2 3 4
3 3 3 3
Sample Output
90
想法
一个显然的想法是,暴力用并查集把一样的位置并起来
最后查询有多少个并查集,设有 \(x\) 个,则最终答案是 \(9 \times 10^{n-1}\) (最高位不能为零)
但显然超时。
考虑怎么优化连边——倍增。
注意到上面连的边数过多的原因是有许多无用边(比如可能有许多边的作用都是让 \(u\) 与 \(v\) 连起来;或者一个大小为 \(n\) 的并查集中有用边只有 \(n-1\) 条,却在内部连了很多条边)
那有一种极巧妙的做法是加一些新点代表一个个长度为 \(2^i\) 的区间,有点类似 \(ST\) 表
每次合并把 \([l,r]\) 拆成 \(O(logn)\) 段区间,把代表那些区间的点对应并起来
最后下放。如原本代表 \([l1,r1]\) 与 \([l2,r2]\) 的点在一个并查集中,那么将 \([l1,(l1+r1)>>1]\) 与 \([l2,(l2+r2)>>1]\) 并起来,将 \([(l1+r1)>>1+1,r1]\) 和 \([(l2+r2)>>1+1,r2]\) 并起来即可
下放的总复杂度是 \(O(nlogn)\) 的
下放到最后就是代表长度为1的区间的点了,找一下并查集个数就可以了。
总复杂度 \(O(logn)\)
太巧妙了!神仙方法 \(orz\)
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#define P 1000000007
using namespace std;
int read(){
int x=0;
char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x;
}
const int N = 100005;
int n,m;
int f[N][18],cnt,ch[18*N][2],fa[N*18];
int getfa(int x) { return x==fa[x] ? x : fa[x]=getfa(fa[x]) ; }
void unit(int x,int y){
x=getfa(x); y=getfa(y);
if(x!=y) fa[x]=y;
}
int Pow_mod(int x,int y){
int ret=1;
while(y){
if(y&1) ret=1ll*ret*x%P;
x=1ll*x*x%P;
y>>=1;
}
return ret;
}
int main()
{
n=read(); m=read();
int l1,l2,r1,r2;
for(int j=0;j<18;j++){
int l=(1<<j);
for(int i=1;i+l-1<=n;i++){
f[i][j]=++cnt;
if(j==0) continue;
ch[cnt][0]=f[i][j-1]; ch[cnt][1]=f[i+(l>>1)][j-1];
}
}
for(int i=1;i<=cnt;i++) fa[i]=i;
while(m--){
l1=read(); r1=read(); l2=read(); r2=read();
for(int i=17;i>=0;i--){
if(l1+(1<<i)-1>r1) continue;
unit(f[l1][i],f[l2][i]);
l1+=(1<<i); l2+=(1<<i);
}
}
for(int i=cnt;i>n;i--)
if(fa[i]!=i){
unit(ch[fa[i]][1],ch[i][1]);
unit(ch[fa[i]][0],ch[i][0]);
}
int ans=0;
for(int i=1;i<=n;i++) if(fa[i]==i) ans++;
printf("%d\n",1ll*9*Pow_mod(10,ans-1)%P);
return 0;
}
[bzoj4569] [loj#2014] [Scoi2016] 萌萌哒的更多相关文章
- [BZOJ4569] [Luogu 3295] [SCOI2016]萌萌哒(并查集+倍增)
[BZOJ4569] [Luogu 3295] [SCOI2016]萌萌哒(并查集+倍增) 题面 有一个n位的十进制数a(无前导0),给出m条限制,每条限制\((l_1,r_1,l_2,r_2)(保证 ...
- 【BZOJ4569】[Scoi2016]萌萌哒 倍增+并查集
[BZOJ4569][Scoi2016]萌萌哒 Description 一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条件表示为四 ...
- 【BZOJ 4569】 4569: [Scoi2016]萌萌哒 (倍增+并查集)
4569: [Scoi2016]萌萌哒 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 865 Solved: 414 Description 一个长 ...
- 【LG3295】[SCOI2016]萌萌哒
[LG3295][SCOI2016]萌萌哒 题面 洛谷 题解 考虑现在我们如果一次只是限定两个位置相等该怎么做, 直接将这些位置用并查集并起来然后答案就是 \[ ans= \begin{cases} ...
- 4569: [Scoi2016]萌萌哒
4569: [Scoi2016]萌萌哒 链接 分析: 每次给出的两个区间长度是一样的,对应位置的数字也是一样的,那么可以将两两对应的数字用并查集合并,设最后有$cnt$个不同的集合,答案就是$9\ti ...
- Luogu P3295 [SCOI2016]萌萌哒(并查集+倍增)
P3295 [SCOI2016]萌萌哒 题面 题目描述 一个长度为 \(n\) 的大数,用 \(S_1S_2S_3 \cdots S_n\) 表示,其中 \(S_i\) 表示数的第 \(i\) 位, ...
- 洛谷P3295 [SCOI2016]萌萌哒 题解
洛谷P3295 [SCOI2016]萌萌哒 题目描述 公式粘过来就乱了,还是去洛谷看题吧 分析 如果暴力解决的话就是使用并查集把位数相同的数位并在一起.比如区间[1,2]和区间[3,4]的数字完全相同 ...
- LOJ#2014「SCOI2016」萌萌哒(倍增,并查集优化连边)
题面 点此看题 题意很明白,就不转述了吧. 题解 题目相当于告诉了我们若干等量关系,每个限制 l 1 , r 1 , l 2 , r 2 \tt l_1,r_1,l_2,r_2 l1,r1,l2 ...
- BZOJ4569 SCOI2016萌萌哒(倍增+并查集)
一个显然的暴力是用并查集记录哪些位之间是相等的.但是这样需要连nm条边,而实际上至多只有n条边是有用的,冗余过多. 于是考虑优化.使用类似st表的东西,f[i][j]表示i~i+2^j-1与f[i][ ...
随机推荐
- 2018-10-19-C#-AddRange-添加位置
title author date CreateTime categories C# AddRange 添加位置 lindexi 2018-10-19 9:3:8 +0800 2018-2-13 17 ...
- ZR1158
ZR1158 http://www.zhengruioi.com/contest/446/problem/1158 给定限制的问题大多数都是容斥或者二分,或者二分之后容斥 首先,这个问题的第一步我们还 ...
- API自动化测试指南
我相信自动化技能已经成为高级测试工程师总体技能的标配.敏捷和持续测试破坏了传统的测试自动化实践,导致测试工程师重新考虑自动化的完成方式.当今的自动化工程师需要在GUI的下方深入到API级别完成软件质量 ...
- Destoon系统目录树SEO属性目录开发实例
如何在destoon里设置树形目录结构的SEO优化方式官方给的SEO伪静态实例是没有这个方式的 楼主后来想了一下,就干脆自己做一个吧,已经测试完全无误通过,特意分享给大家 目前比如sell模块下类别[ ...
- Java 学习笔记(11)——异常处理
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的. 比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error:如果你用System.ou ...
- Qt configure 参数说明(中文)
Qt configure 在编译QT前,可加各种参数来定制自己想要的QT库.这对需要裁减QT库的朋友来说非常重要.对于如何编译QT,可以参考:http://hi.baidu.com/agassi%5F ...
- ELK学习实验010:Logstash简介
Logstash是具有实时流水线功能的开源数据收集引擎.Logstash可以动态统一来自不同来源的数据,并将数据规范化为您选择的目标.清除所有数据并使其民主化,以用于各种高级下游分析和可视化用例. 虽 ...
- IntelliJ Idea中的 Facets 与 Artifacts
在公司和家用电脑上不同版本的idea做实验发现过程中会有些不同,遇到过一些问题,也正是这些问题使得自己能更进一步了解项目构建过程中的细节,特别记录一下. 这个是[温故知新] Java web 开发 ...
- 分支结构,for循环,while循环,跳出循环
#流程控制 概念:通过规定的语句让程序代码有条件的按照一定的方 式执行 顺序结构 按照书写顺序来执行,是程序中最基本的流程结构 选择结构(分支结构.条件结构) 分支结构 单路分支:if(执行的条件){ ...
- 组件的props属性和state状态
props属性: 我使用代码来说明React中props属性: // Profile.jsx import React from 'react' ; export default Class Prof ...