听了很久又看了很久别人的程序才听懂,于是乎记录一下防止以后忘记。
好啦,假设当前
l-1=5,r=7;那如果学习过树状数组的话就知道题目中的操作如果转换为二进制的话
对于l-1来说他的二进制是101,所以会被加上-1的位置是101和100,r的二进制是111,所以会被加上1的位置是111,110,100
所以可以发现最后更新的位置是l-1的二进制的1的个数+r的二进制的1的个数-2*l-1和r都会更新的位置。
而l-1和r减1都会更新的位置的个数是它们两个二进制的最长公共前缀的1的个数(当然,前提是两个二进制的长度相等,要不然更新的位置不可能相同)
那先从简单的开始讨论,我们假设当前的n=1000000(64)
位数i:6 5 4 3 2 1 0
数字:1 0 0 0 0 0 0
方法一:
我们来讨论当前在第i位数字如果是1的话在多少组l-1和r中这个位置是会被更新的(不会抵消),假设i=4
比如说0110000这个数字中的第四位数和0~n这几个数字中的哪些数字是不起冲突可以更新答案的,很明显位数与它不同的肯定不会有矛盾,和它前缀不同的也不可能有矛盾
所以只有0110000~0111111这几个数会和0110000抵消也就是2^4个数,所以这个数能贡献的就是总共的n+1个数减去2^4,好同理而论,在讨论第i位的时候与0110000这个数类似的数总共有2(也就是当第四位的前缀为00~01,总共两种可能)*(2^4)(后面是0000~1111),再乘上之前的(n+1-2^4)就是这位数能为答案贡献的大小。
但是还有另外一种情况,假设n=101111,还是讨论第4位数,你会发现除了上面提到的,还有101000~101111这些数是有可能对答案贡献的,假设这样的数有x个,与上面相同
总贡献就是x*(n+1-x)。所以我们在算每一个数的时候如果当前的这位数为1那么还要再额外多计算一项。
额复杂度基本上就是n的二进制的位数了吧。。。所以跑的飞快。。。
方法二:
哈,数位dp的方法等下再写。。。