P1047,学到了珂朵莉树!

为何要用树状数组?只是为了炫耀你们的学识吗?用模拟难道不是更好吗?

——为何要用模拟?只是为了炫耀你们的学识吗?用线段树难道不是更好吗?

——为何要用线段树?只是为了炫耀你们的学识吗?用分块难道不是更好吗?

——为何要用分块?只是为了炫耀你们的学识吗?用珂朵莉树难道不是更好吗?

(以上改编自本题一题解的评论qwq)

小蒟蒻终于有机会写一道这么难的题的题解了,So exciting!

看了上面的一段话,各位巨佬一定已经明白小蒟蒻这篇题解想讲的是什么了,但是

珂朵莉树是个什么东西?

肯定有人想问这个问题,小蒟蒻这里先不说,各位暂且看看小蒟蒻做这道题的心路历程QωQ

在刚学OI的时候,小蒟蒻最开始自然是用模拟做的,直接N方暴力覆盖,最后再去查询qwq

之后小蒟蒻接触了线段树,感觉线段树这东西好好用呀,手里拿着锤子看什么都是钉子,结果就重新发现了这道神题,一开始还调了不少时间,后来发现其实就是个线段树的板子qwq,初始值都赋为1,update赋值为0,最后query求和一下就完事了(这道题因为是统计全部区间可以直接输出ans[1])

之后小蒟蒻有去学了分块感觉分块这东西也好好用呀,把数列分成根号n块,对于散块直接暴力修改,整块打个tag,同时要维护一个ans数组,保存每个块内的答案。查询因为是从0~n,一定都是整块,小蒟蒻就偷了个懒,直接把所有的ans加起来了。

以上三种方法的代码在题解最后给出)

好了,终于要进入今天的正题了!

观察题目:区间赋值为0

选择珂朵莉树

简单介绍一下,珂朵莉树是一种基于set的暴力数据结构

珂朵莉树的关键在于推平一段区间,即把一段区间的数变的一样(似乎所有珂朵莉树的讲解里面都说了这一句话)

对每一个点建立一个集合

当需要修改的时候,就把要修改区间分成两部分,一部分是需要修改的,一部分是不需要修改的,返回需要修改的地址;

然后把这一段区间内所有的集合都删掉,用一个大集合代替之就可以了。

long_and_num = input().split( )

long = int(long_and_num[0])

num = int(long_and_num[1])

i = 0; all_ = []

while i <= long:

    all_.append(i)

    # print(all_)

    i += 1

i = 0

while i < num:

    part = input().split( )

    start = int(part[0])

    end = int(part[1])

    for a in range(start,end+1):

        if a in all_:

            # print(a)

            all_[a] = -1

    i += 1

answer = 0

for a in all_:

    if a != -1:

        answer += 1

print(answer)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容