最近在学习python3,学习语言最好的方法当然是竞赛题刷刷刷啦
题目连接:https://www.luogu.org/problem/P1047
思路:把被覆盖的线段的两个端点分别放入两个list中,每次有新的点进来的时候先与原来的点对比一下。有没有重叠的地方,有就合并,没有就添加。最后减去每条线段上的数值就是ans啦
代码如下
// An highlighted block
li=input().split()#python 写题目输入方法:读进一个字符串,然后分解到list当中
L=int(li[0])#python输入进来的是字符,要整型转换一下
m=int(li[1])
s=set(li)#set和C++STL的set一样,查重,关键代码会讲解
s.clear()#清除一波
l=[]#创建空list,他不像c里面的数组专门开辟一块空间储存数据
r=[]
def check(x,y)://实现思路的函数,不再多讲
for i in range(len(l)):
if x>l[i] and x<r[i]: #左端点被包含
if y>r[i]: #子集
r[i]=y
return
elif x<l[i] : #左端点在左边
if l[i]>y: #无交集
l.append(x)
r.append(y)
elif r[i]>y:
l[i]=x
else:
l[i]=x
r[i]=y
return
else:
l.append(x)
r.append(y)//list添加数据的方式
return
for i in range(0,m):
li=input().split()
x=int(li[0])
y=int(li[1])
if not l://空的时候直接添加
l.append(x)
r.append(y)
else:
check(x,y)
'''调试用
print(i,":")
print(l)
print(r)
print("--------")
'''
#問題があるんだ、
sit=0
gg=-1
while len(l)+gg>0:
x=l.pop(gg)
y=r.pop(gg)
s.add(x)
check(x,y)
if l[gg] in s:
gg-=1
#-----------加上这个就AC了
L+=1
for i in range(len(l)):
L-=(r[i]-l[i]+1)
print (L)
#一开始没加上述一段代码的时候只有40分,下了一个测试点后发现出大事了
第100次check后发现,l[1],r[1]是l[0],r[0]的一个子集,但是一开始并不是的
原因:数据在增加的过程中基本都被第一个数据给吸收了,一开始不属于第一个范围内的数据现在属于了。
解决方法:让list再自我check一遍,该合并的就合并
gg=-1
while len(l)+gg>0: //list的长度就这么长,如果len+gg=0了那也说明都check一遍了
x=l.pop(gg)//pop函数默认弹出最后的数据,-1也代表倒数第一个数据
y=r.pop(gg)
s.add(x)//将他放入set之中。
check(x,y)
if l[gg] in s: //如果最后的数据还是不属于任何一个线段那肯定会被重新添加,
gg-=1 //如果set中有他那我们就pop他前面的一组数据
这一段自我感觉好巧妙(主要是因为我太菜了ハハハハ~)
PS:这是本人第一次写博客,一定会有很多不足的地方,还请大家可以不吝赐教。
PSS:一开始还是用#注释的,写到最后还是忍不住用 // 了,QAQ
感受:python的set等这一块好像比C++爽多了。
刚想起来:一开始我是想用dict去做(C++的map)但是写完才发现dict在遍历的过程中不能被修改,所以还是选择了list去做0.0一题干了我几个小时我还是太菜了TAT