为何要用树状数组?只是为了炫耀你们的学识吗?用模拟难道不是更好吗?
——为何要用模拟?只是为了炫耀你们的学识吗?用线段树难道不是更好吗?
——为何要用线段树?只是为了炫耀你们的学识吗?用分块难道不是更好吗?
——为何要用分块?只是为了炫耀你们的学识吗?用珂朵莉树难道不是更好吗?
(以上改编自本题一题解的评论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)