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. ElasticStack系列之十七 & 大文本搜索性能提升方案

    1. 什么是大文本?具体是什么? 首先需要理解,ElasticSearch 建立索引完成全文检索的前提是将待检索的信息导入到 ElasticSearch 中.而有的信息对应的正文内容会非常的打,可能达 ...

  2. 比特币全节点(bitcoind) eth 全节点

    运行全节点的用途:  1.挖矿  2.钱包   运行全节点,可以做关于btc的任何事情,例如创建钱包地址.管理钱包地址.发送交易.查询全网的交易信息等等 选个节点钱包:bitcoind 1.配置文件: ...

  3. 转载自知乎大神---this 的值到底是什么?一次说清楚

    你可能遇到过这样的 JS 面试题: var obj = { foo: function(){ console.log(this) } } var bar = obj.foo obj.foo() // ...

  4. header()跳转

    if ($toNews == 1) { header('Location:/ucenter/pageMailBox/2'); exit; } PHP跳转页面,用 header() 函数 定义和用法 h ...

  5. 第9月第12天 lua_push lua_to luaL_check stack quick

    1. c代码中通过lua_push 把数据压入堆栈,lua调用c函数得到数据.luaL_check是对lua_to的封装,从堆栈中获取lua代码中函数调用的数据. static int lread(l ...

  6. CSS background汇总

    本文更新版本 ,请跳转 所有背景属性都不能继承. 1.    background-color 所有元素都能设置背景颜色. background-color的默认值是transparent:也就是说, ...

  7. plsql 用法和技巧

    1.导入csv文件 2.保存登录的密码

  8. 洛谷 P5089: CodeForces #500 (Div. 1) B / 1012B : Chemical table

    题目传送门:洛谷P5089. 题意简述: 一张 \(n \times m\) 的表格,有一些格子有标记,另外一些格子没有标记. 如果 \((r_1,c_1),(r_1,c_2),(r_2,c_1)\) ...

  9. 八、mini2440裸机程序之UART(1)简单介绍【转】

    转自:http://blog.csdn.net/shengnan_wu/article/details/8298869 一.概述          S3C2440通用异步接收和发送(UART)提供了三 ...

  10. mysql 获取当月日期天数

    本月总共天数:SELECT  TIMESTAMPDIFF(day,CURDATE(),(DATE_add(CURDATE(),INTERVAL 1 month)))