题目

有一个长度为\(n\)的十进制数,用\(s\)表示。有\(m\)个限制条件,每个条件形如:\((l_1,r_1,l_2,r_2)\),表示\(s[l_1:r_1]=s[l_2:r_2]\)。

现在给出这些限制条件,问有多少个数满足条件。

\(n,m\le 10^5\) 。

分析

这个题这是神奇!!

首先如果暴力的话,那么我们是把每一个条件的每一个对应位用并查集并起来,最后统计集合的个数\(x\),就可以用\(9*10^{x-1}\)来计算答案了(第一位所在的集合只能填1-9)。

然而限制条件数特别多,暴力显然是不行的。最开始想的是线段树,然而不会做。

考虑类似ST表的方法,我们把这个区间划分成前\(2^j\)位和后\(2^j\)位,那么就变成了这两端\(2^j\)位分别对应相同。我们开\(\log n\)个并查集,每一层记录对应\(j\)的相同性,我们就可以快速处理完每个条件了。

处理完所有条件之后,我们会得到\(\log n\)个并查集,第\(j\)个并查集的\(x,y\)在同一个集合中就表示\(s[x:x+2^j-1]=s[y:y+2^j-1]\)。我们从上往下(\(j\)从大到小)把这个相同性推到下一层去,就可以在总时间\(O((n+m)\log n\cdot \alpha (n))\)的复杂度内得到最后的并查集。最后扫一遍得到集合数即可。

这题中先用ST表思想处理条件,最后统计的方法是很妙的。

代码

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long giant;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=1e5+1;
const int maxj=17;
const int q=1e9+7;
int bin[maxn],n;
inline int Multi(int x,int y) {return (giant)x*y%q;}
inline int mi(int x,int y) {
int ret=1;
for (;y;y>>=1,x=Multi(x,x)) if (y&1) ret=Multi(ret,x);
return ret;
}
struct SET {
int f[maxn];
void init(int n) {for (int i=1;i<=n;++i) f[i]=i;}
int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
int merge(int x,int y) {
int fx=find(x),fy=find(y);
if (fx!=fy) f[fx]=fy;
}
} st[maxj];
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
n=read();
for (int i=2;i<=n;++i) bin[i]=bin[i>>1]+1;
for (int i=bin[n];i>=0;--i) st[i].init(n);
for (int m=read();m;--m) {
int x=read(),y=read(),l=read(),r=read(),len=r-l+1,d=bin[len];
st[d].merge(x,l);
st[d].merge(y-(1<<d)+1,r-(1<<d)+1);
}
for (int j=bin[n];j;--j) {
for (int i=1;i+(1<<j)-1<=n;++i) {
int p=st[j].find(i);
st[j-1].merge(i,p);
st[j-1].merge(i+(1<<(j-1)),p+(1<<(j-1)));
}
}
int cnt=0;
for (int i=1;i<=n;++i) cnt+=(st[0].find(i)==i);
int ans=Multi(9,mi(10,cnt-1));
printf("%d\n",ans);
return 0;
}

最新文章

  1. 【代码笔记】iOS-中国地图
  2. sys.dm_os_waiting_tasks 引发的疑问(下)
  3. SQL Server 2008 R2 Developer (x86, x64, ia64) – DVD (Chinese-Simplified)
  4. Digital Imaging Processing 数字图像处理
  5. [转] Bound Service的三种方式(Binder、 Messenger、 AIDL)
  6. ExtJs API 下载以及部署
  7. codeforces 672 D
  8. 了解JVM
  9. 第6章 堆排序,d叉堆,优先队列
  10. 美团--Quake全链路压测平台
  11. R和Tableau平行坐标图
  12. 廖雪峰Java2面向对象编程-3继承和多态-2多态
  13. 洛谷P1133 教主的花园
  14. There is no Action mapped for namespace / and action name login. - [unknown location]
  15. mongodb3.2副本集配置
  16. gitignore不起作用解决的方法
  17. python 中几个层次的中文编码.md
  18. C的指针疑惑:C和指针10(结构和联合)
  19. Win10启动盘制作工具
  20. javascript js自执行函数

热门文章

  1. U盘装系统流程_U启动
  2. 20155321 2016-2017-2《Java程序设计》课堂实践项目
  3. 实现Django ORM admin view中model字段choices取值自动更新的一种方法
  4. angular promise $q 异步调用
  5. Python爬虫与反爬虫(7)
  6. openstack系列文章(三)
  7. 【Python进阶】无论API怎么变,SDK都可以根据URL实现完全动态的调用
  8. 互评Alpha版本——基于NABCD评论作品,及改进建议
  9. OOP 1.3 动态内存分配
  10. lintcode-512-解码方法