当区间\([a,b]\)和\([c,d]\)对应相等时。

我们把两个区间对应位置上的数所在并查集合并。

最后并查集的数量为\(num\)答案就是\(9*10^num\)因为是个数,不能有前置\(0\)。

但是两个区间对应位置上的数所在并查集合并太浪费时间。

怎么办。

考虑使用倍增。

我们用\((i,j)\)代表\([i,i+(1<<j)-1]\)这个区间然后任何一个区间最多可以\(log\)个这样的倍增的区间拼起来。

然后呢?

我们按倍增区间的大小从大往小枚举。当\((x,i)\)和\((y,i)\)在一个并查集里时,\((x,i-1)\)和\((y,i-1)\)在一个并查集里。\((x+(1<<i-1),i-1)\)和\((y+(1<<i-1),i-1)\)也在一个并查集里。我们把这两对倍增区间所在并查集合并,最后长度为\(1\)的元素所在并查集也被合并。复杂度为\(O(nlogn)\)。

吐槽一波题目

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define int long long
const int mod=1e9+7;
const int N=101000;
int fa[N*22],id[N][22],pw[22],n,m,ans,book[N],tot,xb[N*22],l[N*22];
int find(int x){
if(fa[x]==x)return x;
else return fa[x]=find(fa[x]);
}
int ksm(int x,int b){
int tmp=1;
while(b){
if(b&1)tmp=tmp*x%mod;
b>>=1;
x=x*x%mod;
}
return tmp;
}
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
void pre_work(int x){
pw[0]=1;
for(int i=1;i<=20;i++)pw[i]=pw[i-1]*2;
int len=log2(x);
for(int j=0;j<=len;j++)
for(int i=1;i+pw[j]-1<=n;i++)
id[i][j]=++tot,xb[tot]=i,l[tot]=j,fa[tot]=tot;
}
signed main(){
n=read();m=read();
pre_work(n);
while(m--){
int a=read(),b=read();
int c=read(),d=read();
for(int i=20;i>=0;i--)
if(a+pw[i]-1<=b){
int x=find(id[a][i]),y=find(id[c][i]);
if(x!=y)fa[x]=y;
a=a+pw[i];c=c+pw[i];
}
}
int len=log2(n);
for(int j=len;j>=1;j--)
for(int i=1;i+pw[j]-1<=n;i++){
int f=find(id[i][j]);
int x=find(id[i][j-1]);
int y=find(id[xb[f]][l[f]-1]);
if(x!=y)fa[x]=y;
x=find(id[i+pw[j-1]][j-1]);
y=find(id[xb[f]+pw[l[f]-1]][l[f]-1]);
if(x!=y)fa[x]=y;
}
for(int i=1;i<=n;i++){
int x=find(id[i][0]);
if(book[x]==0)ans++,book[x]=1;
}
printf("%lld",9ll*ksm(10,ans-1)%mod);
return 0;
}

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

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

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

  2. [SCOI2016]萌萌哒(倍增+并查集)

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

  3. [BZOJ4569][SCOI2016]萌萌哒(倍增+并查集)

    首先有一个显然的$O(n^2)$暴力做法,将每个位置看成点,然后将所有限制相等的数之间用并查集合并,最后答案就是9*(10^连通块的个数).(特判n=1时就是10). 然后比较容易想到的是,由于每次合 ...

  4. 2018.07.31 bzoj4569: [Scoi2016]萌萌哒(并查集+倍增)

    传送门 对于每个限制,使用倍增的二进制拆分思想,用并查集数组fa[i][j]" role="presentation" style="position: rel ...

  5. BZOJ4569 [SCOI2016]萌萌哒 【并查集 + 倍增】

    题目链接 BZOJ4569 题解 倍增的思想很棒 题目实际上就是每次让我们合并两个区间对应位置的数,最后的答案\(ans = 9 \times 10^{tot - 1}\),\(tot\)是联通块数, ...

  6. BZOJ4569 [Scoi2016]萌萌哒(并查集,倍增)

    类似\(ST表\)的思想,倍增\(log(n)\)地合并 你是我家的吗?不是就来呀啦啦啦.还有要来的吗?没了!那有多少个家就映射多少答案呀 倍增原来这么好玩 #include <iostream ...

  7. 洛谷P3295 萌萌哒 [SCOI2016] 倍增+并查集

    正解:倍增+并查集 解题报告: 传送门! 首先不难想到暴力?就考虑把区间相等转化成对应点对相等,然后直接对应点连边,最后求有几个连通块就好辣 然后看下复杂度,修改是O(n2)查询是O(n),就比较容易 ...

  8. 【BZOJ4569】萌萌哒(并查集,倍增)

    [BZOJ4569]萌萌哒(并查集,倍增) 题面 BZOJ 题意: 有一个长度为\(n\)的数 给定\(m\)个限制条件 每次限制\(l1-r1\)与\(l2-r2\)是相同的 求出方案数 题解 如果 ...

  9. 【BZOJ 4569】 4569: [Scoi2016]萌萌哒 (倍增+并查集)

    4569: [Scoi2016]萌萌哒 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 865  Solved: 414 Description 一个长 ...

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

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

随机推荐

  1. 孟晓阳:IT运行监控系统设计与使用心得

    http://www.cn-healthcare.com/article/20160325/content-482138.html

  2. 【ACM】hdu_1092_A+BIV_201307261630

    A+B for Input-Output Practice (IV)Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/3276 ...

  3. 自建X509证书

    X509证书是需要买的,自己建的证书不会被浏览器认可,会弹出提示安全不受保障的页面. 学习一下如何建,实际用到还是要买. 打开vs2015开发员人员命令提示 输入创建证书的命令 Makecert.ex ...

  4. [React] Refactor componentWillReceiveProps() to getDerivedStateFromProps() in React 16.3

    The componentWillReceiveProps() method is being deprecated in future version of React (17). Many of ...

  5. HDU 5402 Travelling Salesman Problem (模拟 有规律)(左上角到右下角路径权值最大,输出路径)

    Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (J ...

  6. 并查集图冲突hdu1272

    还是属于并查集的变形 两个点仅仅有一条路径连通 给出的两个点事先都是属于两个集合的 须要给出的着条边构成一个集合 算法复杂度还是挺高的 每一个我都循环了100000次 set2数组没清空 wrong了 ...

  7. 齐头并进完成任务——Java多线程(一)

    多线程(Multithread)指的是在单个进程中同时运行多个不同的线程,执行不同的任务.多线程意味着一个程序的多行语句块并发执行. 一.实现多线程 1.通过继承Thread类实现多线程. Threa ...

  8. Spring MVC简介 2.5 Spring MVC执行的流程

    package org.fkit.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http ...

  9. web 单一平台登录逻辑

    单点登录逻辑token=cookie('login_token');serverToken=get(token);if(serverToken!='注销'){ set('userid_已登录token ...

  10. subprocess学习

    转自http://blog.csdn.net/imzoer/article/details/8678029 subprocess的目的就是启动一个新的进程并且与之通信. subprocess模块中只定 ...