bzoj4569-萌萌哒
题目
有一个长度为\(n\)的十进制数,用\(s\)表示。有\(m\)个限制条件,每个条件形如:\((l_1,r_1,l_2,r_2)\),表示\(s[l_1:r_1]=s[l_2:r_2]\)。
现在给出这些限制条件,问有多少个数满足条件。
\(n,m\le 10^5\) 。
分析
这个题这是神奇!!
首先如果暴力的话,那么我们是把每一个条件的每一个对应位用并查集并起来,最后统计集合的个数\(x\),就可以用\(9*10^{x-1}\)来计算答案了(第一位所在的集合只能填1-9)。
然而限制条件数特别多,暴力显然是不行的。最开始想的是线段树,然而不会做。
考虑类似ST表的方法,我们把这个区间划分成前\(2^j\)位和后\(2^j\)位,那么就变成了这两端\(2^j\)位分别对应相同。我们开\(\log n\)个并查集,每一层记录对应\(j\)的相同性,我们就可以快速处理完每个条件了。
处理完所有条件之后,我们会得到\(\log n\)个并查集,第\(j\)个并查集的\(x,y\)在同一个集合中就表示\(s[x:x+2^j-1]=s[y:y+2^j-1]\)。我们从上往下(\(j\)从大到小)把这个相同性推到下一层去,就可以在总时间\(O((n+m)\log n\cdot \alpha (n))\)的复杂度内得到最后的并查集。最后扫一遍得到集合数即可。
这题中先用ST表思想处理条件,最后统计的方法是很妙的。
代码
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long giant;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=1e5+1;
const int maxj=17;
const int q=1e9+7;
int bin[maxn],n;
inline int Multi(int x,int y) {return (giant)x*y%q;}
inline int mi(int x,int y) {
int ret=1;
for (;y;y>>=1,x=Multi(x,x)) if (y&1) ret=Multi(ret,x);
return ret;
}
struct SET {
int f[maxn];
void init(int n) {for (int i=1;i<=n;++i) f[i]=i;}
int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
int merge(int x,int y) {
int fx=find(x),fy=find(y);
if (fx!=fy) f[fx]=fy;
}
} st[maxj];
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
n=read();
for (int i=2;i<=n;++i) bin[i]=bin[i>>1]+1;
for (int i=bin[n];i>=0;--i) st[i].init(n);
for (int m=read();m;--m) {
int x=read(),y=read(),l=read(),r=read(),len=r-l+1,d=bin[len];
st[d].merge(x,l);
st[d].merge(y-(1<<d)+1,r-(1<<d)+1);
}
for (int j=bin[n];j;--j) {
for (int i=1;i+(1<<j)-1<=n;++i) {
int p=st[j].find(i);
st[j-1].merge(i,p);
st[j-1].merge(i+(1<<(j-1)),p+(1<<(j-1)));
}
}
int cnt=0;
for (int i=1;i<=n;++i) cnt+=(st[0].find(i)==i);
int ans=Multi(9,mi(10,cnt-1));
printf("%d\n",ans);
return 0;
}
bzoj4569-萌萌哒的更多相关文章
- 【BZOJ4569】萌萌哒(并查集,倍增)
[BZOJ4569]萌萌哒(并查集,倍增) 题面 BZOJ 题意: 有一个长度为\(n\)的数 给定\(m\)个限制条件 每次限制\(l1-r1\)与\(l2-r2\)是相同的 求出方案数 题解 如果 ...
- 【BZOJ4569】[Scoi2016]萌萌哒 倍增+并查集
[BZOJ4569][Scoi2016]萌萌哒 Description 一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条件表示为四 ...
- [BZOJ4569] [Luogu 3295] [SCOI2016]萌萌哒(并查集+倍增)
[BZOJ4569] [Luogu 3295] [SCOI2016]萌萌哒(并查集+倍增) 题面 有一个n位的十进制数a(无前导0),给出m条限制,每条限制\((l_1,r_1,l_2,r_2)(保证 ...
- 【BZOJ-4569】萌萌哒 ST表 + 并查集
4569: [Scoi2016]萌萌哒 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 459 Solved: 209[Submit][Status] ...
- 【bzoj4569 scoi2016】萌萌哒
题目描述 一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条件表示为四个数,l1,r1,l2,r2,即两个长度相同的区间,表示子串S ...
- BZOJ4569 SCOI2016萌萌哒(倍增+并查集)
一个显然的暴力是用并查集记录哪些位之间是相等的.但是这样需要连nm条边,而实际上至多只有n条边是有用的,冗余过多. 于是考虑优化.使用类似st表的东西,f[i][j]表示i~i+2^j-1与f[i][ ...
- [BZOJ4569][SCOI2016]萌萌哒(倍增+并查集)
首先有一个显然的$O(n^2)$暴力做法,将每个位置看成点,然后将所有限制相等的数之间用并查集合并,最后答案就是9*(10^连通块的个数).(特判n=1时就是10). 然后比较容易想到的是,由于每次合 ...
- BZOJ4569 [SCOI2016]萌萌哒 【并查集 + 倍增】
题目链接 BZOJ4569 题解 倍增的思想很棒 题目实际上就是每次让我们合并两个区间对应位置的数,最后的答案\(ans = 9 \times 10^{tot - 1}\),\(tot\)是联通块数, ...
- BZOJ4569 : [Scoi2016]萌萌哒
建立ST表,每层维护一个并查集. 每个信息可以拆成两条长度为$2$的幂次的区间相等的信息,等价于ST表里两对点的合并. 然后递归合并,一旦发现已经合并过了就退出. 因为一共只会发生$O(n\log n ...
- 2018.07.31 bzoj4569: [Scoi2016]萌萌哒(并查集+倍增)
传送门 对于每个限制,使用倍增的二进制拆分思想,用并查集数组fa[i][j]" role="presentation" style="position: rel ...
随机推荐
- 20155317 王新玮 2016-2017-2 《Java程序设计》第5周学习总结
20155317 王新玮 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 异常处理 & Collection与Map 异常继承架构 错误的对象继承ja ...
- day 10 字典dict
添加 xxx[新的key] = value 删除 del xx[key] 修改 xxx[已存在的key] = new_value 查询 xxx.get(key) 1. dict 字典 #### lis ...
- 【MYSQL命令】mysql基础命令
1.查询MYSQL当前用户命令:select user() mysql> select user(); +------------------------+ | user() | +------ ...
- 一次性搞定Session
相信很多人遇到过同一个浏览器会出现Session覆盖问题.今天主要针对Session覆盖问题来看看Session是如何工作的.那么先看一张简单的图说明一下 上面的图大致的说明Session工作简单创建 ...
- 【转】在Android Studio中下载Android SDK的两种方式(Android Studio3.0、windows)
在Android Studio中下载Android SDK的两种方式(Android Studio3.0.windows) 方式一.设置HTTP Proxy1. 打开Settings2. 点击HTTP ...
- 【SpringCloud】第十二篇: 断路器监控(Hystrix Turbine)
前言: 必需学会SpringBoot基础知识 简介: spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选. ...
- ython进阶06 循环对象
这一讲的主要目的是为了大家在读Python程序的时候对循环对象有一个基本概念. 循环对象的并不是随着Python的诞生就存在的,但它的发展迅速,特别是Python 3x的时代,循环对象正在成为循环的标 ...
- 百度地图之自动提示--autoComplete
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- MYSQL主从复制配置(整理)
MYSQL主从原理及过程 原理 Mysql的 Replication 是一个异步的复制过程(mysql5.1.7以上版本分为异步复制和半同步两种模式),从一个 Mysql instace(我们称之为 ...
- C++11的左值引用与右值引用总结
概念 在C++11中,区别表达式是左值或右值可以做这样的总结:当一个对象被用作右值的时候,用的是对象的值(内容):当对象被用作左值的时候,用的是对象的身份(在内存中的位置).左值有持久的状态,而右值要 ...