4569: [Scoi2016]萌萌哒

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 865  Solved: 414

Description

一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条
件表示为四个数,l1,r1,l2,r2,即两个长度相同的区间,表示子串Sl1Sl1+1Sl1+2...Sr1与Sl2Sl2+1Sl2+2...S
r2完全相同。比如n=6时,某限制条件l1=1,r1=3,l2=4,r2=6,那么123123,351351均满足条件,但是12012,13
1141不满足条件,前者数的长度不为6,后者第二位与第五位不同。问满足以上所有条件的数有多少个。

Input

第一行两个数n和m,分别表示大数的长度,以及限制条件的个数。接下来m行,对于第i行,有4个数li1,ri1,li2
,ri2,分别表示该限制条件对应的两个区间。
1≤n≤10^5,1≤m≤10^5,1≤li1,ri1,li2,ri2≤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

HINT

Source

【分析】

  这题的方法还是很妙的。虽然说不是怎么新奇但是我还是没想出来嘛。。

  其实个人觉得线段树也是可以的。用线段树上的点表示区间,然后也可以merge。

  倍增也很好打啦。

  f[i][j]表示[i,i+2^j-1]这个区间,同层的区间可以merge。

  m个操作的时候就merge最多log个区间嘛。最后把merge的并查集下放到区间长度小一倍那里就好。

  要细心一点,若全都在一个并查集,答案应该是10而不是9。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Mod 1000000007
#define Maxn 100010
#define Maxd 20 int f[Maxn][Maxd],num[Maxn][Maxd],fa[Maxn*Maxd];
int son[Maxn*Maxd][]; int ffa(int x)
{
if(fa[x]!=x) fa[x]=ffa(fa[x]);
return fa[x];
} void merge(int st1,int st2,int l)
{
for(int j=;j>=;j--)
{
if((<<j)<=l)
{
int x=num[st1][j],y=num[st2][j];
if(ffa(x)!=ffa(y)) fa[ffa(x)]=y;
if((<<j)<l) merge(st1+(<<j),st2+(<<j),l-(<<j));
return;
}
}
} int main()
{
int n,m;
scanf("%d%d",&n,&m);
int cnt=;
for(int j=;(<<j)<=n;j++) for(int i=;i+(<<j)-<=n;i++)
{
num[i][j]=++cnt;
if(j!=) son[cnt][]=num[i][j-],son[cnt][]=num[i+(<<j-)][j-];
}
for(int i=;i<=cnt;i++) fa[i]=i;
for(int i=;i<=m;i++)
{
int l1,r1,l2,r2;
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
merge(l1,l2,r1-l1+);
}
for(int j=;j>;j--)
{
for(int i=;i<=n;i++) if(num[i][j])
{
if(ffa(num[i][j])!=num[i][j])
{
int x=num[i][j],y=ffa(num[i][j]);
if(ffa(son[x][])!=ffa(son[y][])) fa[ffa(son[x][])]=son[y][];
if(ffa(son[x][])!=ffa(son[y][])) fa[ffa(son[x][])]=son[y][];
}
}
}
int ans=,tot=;
for(int i=;i<=n;i++) if(ffa(num[i][])==num[i][])
{
tot++;
if(ans==) ans=1LL*ans*%Mod;
else ans=1LL*ans*%Mod;
}
if(tot==) ans=;
printf("%d\n",ans);
return ;
}

2017-04-27 15:02:37

【BZOJ 4569】 4569: [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. 洛谷P3295 [SCOI2016]萌萌哒(倍增+并查集)

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

随机推荐

  1. [转]Python numpy函数hstack() vstack() stack() dstack() vsplit() concatenate()

    Python numpy函数hstack() vstack() stack() dstack() vsplit() concatenate() 觉得有用的话,欢迎一起讨论相互学习~Follow Me ...

  2. pytho部分命令

    python --version查看版本号 pip install XXX 安装模块 pip uninstall XXX 卸载模块

  3. [python]python三元表达式另类实现方式

    () variable = a if exper else b ()variable = (exper and [b] or [c])[] () variable = exper and b or c

  4. leaflet-velocity 参数

    本文地址: https://www.cnblogs.com/veinyin/p/10769611.html  leaflet-velocity 是 leaflet 绘制风场的一个插件,其控制参数如下所 ...

  5. Hash::make与Hash::check

    调用方法之前要先去引用: use Illuminate\Support\Facades\Hash; 可以调用 Hash 门面上的 make 方法对存储密码进行哈希: $pwd = Hash::make ...

  6. excel中数字如何自动换行

    1. excel中点击单元格右键,选择“设置单元格格式” -- “对齐”选项卡. 2. 先取消“自动换行”,勾选上“缩小字体填充”. 3.再选择“自动换行”即可实现数字的自动换行.

  7. 利用iis虚拟目录实现文件服务器功能

    要求说明: 通过网站上传文件保存到统一的文件服务器上. 服务器说明: 1.文件服务器以下称为FilesServer,IP地址为:192.168.1.213 2.Web服务器为以下称为WebServer ...

  8. SVM Kernel Functions

    ==================================================================== This article came from here. Th ...

  9. Twisted框架

    Twisted是一个事件驱动型的网络模型.时间驱动模型编程是一种范式,这里程序的执行流由外部决定.特点是:包含一个事件循环,当外部事件发生时,使用回调机制来触发相应的处理. 线程模式: 1.单线程同步 ...

  10. mysql grep database error(cannot rmdir /dbname)

    service mysql stop cd /var/lib/mysql/dbname rm -rf .fmr rm -rf .txt service mysql start srop databas ...