[SCOI2016]萌萌哒

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 S1S2S3Sn表示,其中 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+2Sr1 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+2Sr2完全相同。

比如 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=rl+1
拆成 [ l , l + 1 &lt; &lt; l o g l e n ] [l,l + 1&lt;&lt;loglen] [l,l+1<<loglen] [ r − 1 &lt; &lt; l o g l e n + 1 , r ] [r -1&lt;&lt;loglen+1,r] [r1<<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);
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值