NOI2015软件包管理器,大力卡常记

其实此题并不卡常,只是昨天有人说这题全是0/1操作,或许可以压位,然后我采纳这个idea,刷了下榜。
一开始我把朴素线段树给直接换成压位,因为复杂度太大,并不比常数正常的线段树快。这里是纯压位代码
之后根据今年NOI2017D1T1压位线段树的经验,我把纯压位改成了压位线段树,这是代码
为什么压位线段树的相对于普通线段树的优化力度,并没有压位相对于常规暴力那么大?这是因为在常规问题中,压位优化是从 O(qn) 变成 O(qnw) ,而线段树问题中,压位优化是从 O(qlogn) 变成 O(qlognw) ,即 O(q(lognlogw) ,优化力度从除法变减法。
而且压位需要特殊处理两端的情况,一定程度上增大了常数和代码复杂度,这就导致NOI2017D1T1事后我在UOJ上被卡常。
不过在这题中一定程度上可以减少特殊处理两端时的常数。
首先简要描述下单纯的压位线段树的具体流程:
1.在线段树上找到两端所在块的值;
2.在线段树上修改两端;
3.再对中间的块进行赋值;
注意到区间的两端在线段树相当于单点,这就使我们可以迭代实现操作1和2。(优化1)
又注意到连续的两个1,2操作对象是同一个元素,所以操作2时可以不pushdown(优化2)
再大胆猜测左右端都操作后,中间的块也不用pushdown(优化3)
优化1代码(未迭代实现操作2)
优化1和2代码(未迭代实现操作2)
优化1,2,3代码
上述是宏观层面的卡常,还没用到“有理有据的底层优化”
底层优化1:操作2是直接加上增量,而不是重新maintain->代码
底层优化2:操作1是不用if,而是用三元运算符->代码
底层优化3:操作1是判循环结束不用!=,而是用^->代码
底层优化4:操作1修改循环变量时从三元运算符变成,位移并或上一个布尔表达式->代码
之所以说是底层优化,是因为基础运算次数没有变化
最后,在uoj,洛谷,bzoj,loj上我都拿到rk1
总结一下,在uoj上,复杂度的优化效果为1986ms,代码层面的高级常数优化效果为547ms,底层优化的效果为189ms(可能是我常数优化的能力比较差?但可能不是所有题都适合常数优化)
说了这么多,好像所有优化全是在辅助数据结构上,似乎跟树剖以及初始化(I/O)没有一点关系?
upd:我又发现压位以后线段树的结点范围变小,可以用short存,但实测效果不好(可能没控制变量?欢迎大佬进行试验)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值