洛谷 P1047 校门外的树 python题解

11 篇文章 0 订阅
6 篇文章 1 订阅

最近在学习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)#setC++STLset一样,查重,关键代码会讲解
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
#-----------加上这个就ACL+=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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值