bzoj4569[Scoi2016]萌萌哒
2016-05-20 20:37
471 查看
Description
给出一个有n位的无前导0正整数,再给出m个限制,每个限制形如l1…r1,l2..r2表示这个数的l1~r1位和第l2~r2位是相等的。求这样的数的个数。n,m<=10^5
Solution
我们可以先来考虑一下暴力。对于这一个区间,我们暴力把它们用并查集并起来。
那么100%呢?
我们可以用f[i][j]表示[i~i+2^j-1]这一段区间属于哪一个集合。
若没有则等于0.
那么每次合并我们可以把这个限制拆成log个区间,依次合并起来。
还有,若f[i][j]和f[s][t]同属一个集合,那么f[i][j-1]和f[s][t-1],f[i+2^(j-1)][j-1]和f[s+2^(t-1)][t-1]也同属一个集合。
每次用并查集合并就好了。
Code
#include<cstdio> #include<cstring> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) #define N 100005 #define mo 1000000007 using namespace std; typedef long long ll; int fa[N*17],base[N*17],log[N*17],two[17],id[N][17]; int n,m,tot,l1,l2,r1,r2; int get(int x) { return fa[x]?fa[x]=get(fa[x]):x; } void merge(int x,int y) { x=get(x);y=get(y); if (x!=y) fa[y]=x; } int main() { scanf("%d%d",&n,&m);two[0]=1; fo(i,1,16) two[i]=two[i-1]*2; fo(i,1,n) fo(j,0,16) id[i][j]=++tot,base[tot]=i,log[tot]=j; fo(i,1,m) { scanf("%d%d%d%d",&l1,&r1,&l2,&r2); fd(j,16,0) if (l1+two[j]-1<=r1) { merge(id[l1][j],id[l2][j]); l1+=two[j];l2+=two[j]; } } fd(j,16,1) fo(i,1,n) { int x=get(id[i][j]); int a=base[x],b=log[x]; merge(id[a][b-1],id[i][j-1]); if (i+two[j-1]<=n) merge(id[a+two[b-1]][b-1],id[i+two[j-1]][j-1]); } ll ans=9;bool bz=0; fo(i,1,n) if (!fa[id[i][0]]) { if (bz) ans=ans*10%mo;bz=1; } printf("%lld",ans); }
相关文章推荐
- 【学习心得】分块
- 整理篇
- error: no matching function for call to 'std::basic_ifstream<char>::open(std::string&)
- 逆---LanSet.exe
- Spring的组件装配
- HDU 2586 How far away ? (LCA)
- TensorFlow实战之:Quick Start
- Linux 命令行模式快捷键使用
- 静态碎片切换 和动态viewpage切换和view颜色切换
- microstation level2 0601_2
- Java的线程常用方法
- 安装tensorflow
- 加特征加正则
- POJ 2356 Find a multiple(鸽巢原理(抽屉原理))
- 实习入职第二天:PackageInfo、ResolveInfo
- 啦啦啦啦~Django1.96---编写第一个Django应用(5)
- ML 徒手系列说明
- 10个有关RESTful API良好设计的最佳实践
- HBase中批量修改
- EventBus的使用