BZOJ4569 SCOI2016萌萌哒(倍增+并查集)
一个显然的暴力是用并查集记录哪些位之间是相等的。但是这样需要连nm条边,而实际上至多只有n条边是有用的,冗余过多。
于是考虑优化。使用类似st表的东西,f[i][j]表示i~i+2^j-1与f[i][j]~f[i][j]+2^j-1连接起来了,也就是把这一大段看成一个点所建立的并查集。那么每个限制只要拆成两段就可以了。最后查询的时候,需要把信息下传,即f[i][j]下传到f[i][j-1]和f[i+2^(j-1)][j-1],表示这两段各自分别对应。于是复杂度变成了O(nlognαn)。这个做法能优化复杂度的关键在于每次下传过程中都去除了一些冗余边使其不再会下传了。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() {int x=0,f=1;char c=getchar();while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();return x*f; } #define N 100010 #define P 1000000007 int n,m,fa[N][18],lg2[N],ans=0; int find(int x,int j){return fa[x][j]==x?x:fa[x][j]=find(fa[x][j],j);} void merge(int x,int y,int k){fa[find(x,k)][k]=find(y,k);} int main() { #ifndef ONLINE_JUDGEfreopen("bzoj4569.in","r",stdin);freopen("bzoj4569.out","w",stdout);const char LL[]="%I64d"; #elseconst char LL[]="%lld"; #endifn=read(),m=read();for (int i=1;i<=n;i++)for (int j=0;j<=17;j++)fa[i][j]=i;lg2[1]=0;for (int i=1;i<=n;i++){lg2[i]=lg2[i-1];if ((2<<lg2[i])<=i) lg2[i]++;}for (int i=1;i<=m;i++){int l1=read(),r1=read(),l2=read(),r2=read();merge(l1,l2,lg2[r1-l1+1]);merge(r1-(1<<lg2[r1-l1+1])+1,r2-(1<<lg2[r1-l1+1])+1,lg2[r1-l1+1]);}for (int j=17;j>=1;j--)for (int i=1;i<=n;i++)if (fa[i][j]!=i) merge(i,fa[i][j],j-1),merge(i+(1<<j-1),fa[i][j]+(1<<j-1),j-1);for (int i=1;i<=n;i++) if (find(i,0)==i) ans++;int t=9;for (int i=2;i<=ans;i++) t=10ll*t%P;cout<<t;return 0; }
转载于:https://www.cnblogs.com/Gloid/p/9413633.html
BZOJ4569 SCOI2016萌萌哒(倍增+并查集)相关推荐
- 洛谷P3295 [SCOI2016]萌萌哒(倍增+并查集)
传送门 思路太妙了啊-- 容易才怪想到暴力,把区间内的每一个数字用并查集维护相等,然后设最后总共有$k$个并查集,那么答案就是$9*10^{k-1}$(因为第一位不能为0) 考虑倍增.我们设$f[i] ...
- bzoj4569 [Scoi2016]萌萌哒 并查集+st表
这个题非常巧妙,它描述了一种新的延迟标记关系.. 正常的线段树是用n*4的空间描述一个序列,所以对于一段区间,有可能会有log个点对应一个点 而线段树是利用尽量小的空间使查询变为log st表是nlo ...
- BZOJ4569: [Scoi2016]萌萌哒
4569: [Scoi2016]萌萌哒 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 961 Solved: 464 [Submit][Statu ...
- Codeforces 827D Best Edge Weight 倍增 + 并查集 || 倍增 + 压倍增标记 (看题解)
Best Edge Weight 我们先找出一棵最小生成树, 对于非树边来说, 答案就是两点路径上的最大值 - 1, 这个直接倍增就能处理. 对于树边来说, 就是非树边的路径经过这条边的最小值 - 1 ...
- BZOJ4569 [Scoi2016]萌萌哒
一眼觉得是并查集,yy了一下线段树优化发现不可sing,orz了ljss神犇被告知是倍增优化 倍增,一个点[i][j]代表某个i往后2^j个数,把点按倍增次数分层,两个同层的点在一个连通块说明两个点所 ...
- bzoj4569[Scoi2016]萌萌哒
Description 给出一个有n位的无前导0正整数,再给出m个限制,每个限制形如l1-r1,l2..r2表示这个数的l1~r1位和第l2~r2位是相等的.求这样的数的个数. n,m<=10^ ...
- [bzoj4569][SCOI2016]萌萌哒
题目大意 有一个无前导0的n位数,有m个限制形如[l1,r1]=[l2,r2],问满足条件的数有多少种,答案模10^9+7. 倍增 我们用ST表,f[i,j]表示[i,i+2^j-1]这一段. 那么初 ...
- 1386:打击犯罪(并查集)
[题目描述] 某个地区有n(n≤1000)个犯罪团伙,当地警方按照他们的危险程度由高到低给他们编号为1-n,他们有些团伙之间有直接联系,但是任意两个团伙都可以通过直接或间接的方式联系,这样这里就形成了 ...
- 【BZOJ4569】萌萌哒,ST表+并查集
Time:2016.08.03 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: sunshine爷模拟题之一 自认计数类问题还可以的我找了半天规律也只会50分做法: 对于每个询问直接 ...
- P3295 [SCOI2016]萌萌哒(DP+倍增)
P3295 [SCOI2016]萌萌哒 description solution 强制部分区间相同,很容易就想到了并查集,直接暴力并查集合并是O(n2)O(n^2)O(n2)的 只需要考虑那一个数据结 ...
最新文章
- 【二分答案】【最短路】bzoj1614 [Usaco2007 Jan]Telephone Lines架设电话线
- 相关滤波跟踪(MOSSE)
- C#委托、事件、消息(入门级)
- cisco firewall (ASA Series)
- DirectShow 在VS2005中环境配置
- python处理文件名_[请教]python的中文文件名处理
- TensorFlow教程之API DOC 6.1.1Class tensorflow::Env
- CSS三角制作(HTML、CSS)
- 如何快速成为C++工程师?
- 管理表空间和数据文件——建立表空间——建立字典管理表空间和建立加密表空间...
- 架构师如何才能够设计一个安全的架构
- LVS详解(二)——LVS工作模式
- 采集企业联系方式的10个经典方法
- 基于stm32风力摆控制系统(电赛获得省一)
- 第一章 马克思主义哲学是科学的世界观和方法论
- html风琴图片展示,基于jquery的手风琴图片展示效果实现方法
- phpmywind目录结构
- DOS操作系统的一些常用命令
- ChatGPT如何注册使用(解决国外手机号验证码问题)
- 如何完全卸载你之前版本的MySQL数据库??