给定长为n(n<=1e4)的数组,第i个数为ai(0<=ai<2的60次方)
初始时,区间为[1,n],也即l=1,r=n,
你可以在[l,r)中指定一个k,将区间分成左半边[l,k]、右半边[k+1,r]
1. 如果左半边异或和与异或和的异或和相等,则可以二选一,要么保留左半边,要么保留右半边
2. 否则,只能保留异或和大的那半边
当l=r时,游戏结束
对于每个i,判断是否能通过适当操作,使得游戏结束时l=r=i
实际t(t<=1e4)组样例,保证sumn不超过1e4
力扣群 潼神
这个st[0]和ed[0]实际只需要占一位,分开写的话可读性会好一点
此处由于值域限制,直接维护在了st和ed的第60位
n=1e4,说明只能是O(1)转移的区间dp
异或和的两种情况:
1. [l,r]异或和为0,那么[l,x](x
2. [l,r]异或和为s(s≠0),记s的最高位为b,
那么,如果[l,x](x 同理,如果[y,r](y>l)的异或和包含b这一位,[y,r]的异或和就一定大于[l,y-1]的异或和 ①左端点/右端点第60位打过标记,说明存在共左端点/右端点的更大的区间异或和为0 ②[l,r]异或和为s,s和左端点/右端点的标记有交,说明存在共左端点/右端点的更大的区间的异或和的最高位能被s取到,也就是s比区间另一半大 ①如果异或和为0,在第60位打标记 ②否则,在异或和最高位打标记 本题是长区间向短区间下放,没怎么写过,但本身区间dp也很灵活 由于下放时一定需要固定一个端点,所以可以将信息维护在端点处供后续使用 也就只需要开一维,不像传统区间dp开两位数组那样了 __builtin_clzll(s)是获取64位数二进制前导0个数 63-__builtin_clzll(s)是获取64位数二进制最高位的1是第几位 从右往左,从第0位开始数,也就是1<
32位数时,可以对应改成__builtin_clz(s)、31-__builtin_clz(s)判断
设位
心得
代码
#include