Q u e s t i o n Question Question
一个长度为 n n n 的大数,用 S 1 S 2 S 3 ⋯ S n S_1S_2S_3 \cdots S_n S1S2S3⋯Sn表示,其中 S i S_i Si 表示数的第 i i i 位, S 1 S_1 S1 是数的最高位。告诉你一些限制条件,每个条件表示为四个数, l 1 , r 1 , l 2 , r 2 l_1,r_1,l_2,r_2 l1,r1,l2,r2,即两个长度相同的区间,表示子串 S l 1 S l 1 + 1 S l 1 + 2 ⋯ S r 1 S_{l_1}S_{l_1+1}S_{l_1+2} \cdots S_{r_1} Sl1Sl1+1Sl1+2⋯Sr1与 S l 2 S l 2 + 1 S l 2 + 2 ⋯ S r 2 S_{l_2}S_{l_2+1}S_{l_2+2} \cdots S_{r_2} Sl2Sl2+1Sl2+2⋯Sr2完全相同。
比如 n = 6 n=6 n=6 时,某限制条件 l 1 = 1 , r 1 = 3 , l 2 = 4 , r 2 = 6 l_1=1,r_1=3,l_2=4,r_2=6 l1=1,r1=3,l2=4,r2=6 ,那么 123123 123123 123123, 351351 351351 351351 均满足条件,但是 12012 12012 12012, 131141 131141 131141 不满足条件,前者数的长度不为 6 6 6 ,后者第二位与第五位不同。问满足以上所有条件的数有多少个。
S o l u t i o n Solution Solution
倍增骚操作了解一下
最直观的方法便是
N
2
N^2
N2并查集
它主要慢在了一个一个操作合并
于是我们考虑整个区间合并:
还记得
S
T
ST
ST表是怎样询问的吗?
l
e
n
=
r
−
l
+
1
len = r - l + 1
len=r−l+1
拆成
[
l
,
l
+
1
<
<
l
o
g
l
e
n
]
[l,l + 1<<loglen]
[l,l+1<<loglen]和
[
r
−
1
<
<
l
o
g
l
e
n
+
1
,
r
]
[r -1<<loglen+1,r]
[r−1<<loglen+1,r]
于是,我们可以开
l
o
g
M
A
X
N
logMAXN
logMAXN个并查集
F
a
[
i
]
[
j
]
Fa[i][j]
Fa[i][j]表示左端点为
j
j
j,长度为
2
i
2^i
2i的区间
读入完后就从大到小,将大区间拆成两个
最后统计
F
a
[
0
]
Fa[0]
Fa[0]中集合的个数就可以辣!
给出拆分区间的代码:
for (int i = log[N];i > 0;i--)
{
for (int j = 1;j <= N - (1 << i) + 1;j++)
{
Union(j,Find(j,i),i - 1);
Union(j + (1 << (i - 1)),Find(j,i) + (1 << (i - 1)),i - 1);
}