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 XML梳理

    导入ElementTree模块 import xml.etree.ElementTree as ET 为了创建一个element实例,使用Element 构造函数或者SubElement()工厂函数. ...

  2. .net MVC入门

    这里面之所以没有Sql语句但是也可以对数据库进行数据操作的原因就是Entity Framework.Entity Framework有三种模式,这里用的是Models模式. 网上有太多的.net MV ...

  3. ngx_lua_API 指令详解(三)怎样理解 cosocket指令

    参考:https://moonbingbing.gitbooks.io/openresty-best-practices/content/ngx_lua/whats_cosocket.html 春哥演 ...

  4. li分两列显示

    只要控制了li的宽度,利用浮动就能实现<style type="text/css"> .my ul { width: 210px; } .my li { width: ...

  5. Git 操作指南

    http://blog.csdn.net/troy__/article/details/40082657

  6. 统一过程模型(RUP/UP)

    http://blog.sina.com.cn/s/blog_6a06f1b7010121hz.html 统一过程(RUP/UP,Rational Unified Process)是一种以用例驱动.以 ...

  7. Ubuntu 12.04将默认集成Landscape管理套件【转】

    转自:https://imtx.me/archives/1702.html 今天,我像往常一样对我的Ubuntu 12.04 Beta进行了一次常规升级,然后我发现在系统设置当中多了一个图标,叫「Ma ...

  8. python格式化输出【转】

    今天写代码时,需要统一化输出格式进行,一时想不起具体细节,用了最笨的方法,现在讲常见的方法进行一个总结. 一.格式化输出 1.整数的输出 直接使用'%d'代替可输入十进制数字: >>> ...

  9. 一步步实现windows版ijkplayer系列文章之一——Windows10平台编译ffmpeg 4.0.2,生成ffplay

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  10. Robotium_断言方法assert、is、search

    下面的这些方法都主要用来判断测试结果是否与预期结果相符,一般把is和search方法放在assert里面判断.assert最常用的还是assertThat方法,是Junit的判断,这里就不多说了.断言 ...