当前位置: 代码迷 >> 综合 >> Candy Collection
  详细解决方案

Candy Collection

热度:20   发布时间:2023-12-15 07:35:42.0

题意

有一串糖果箱,每个箱子有颜色,装有一定数量的糖果,然后现在要用大一点的条状箱子把它们运回去,每个条状箱子中装的是一段连续的箱子,不能有相同颜色的箱子,每个箱子的运费是所有箱子糖果数的按位或的和。求最小运费。

1 ≤ 1\leq 1箱子数量 ≤ 5 ? 1 0 5 \leq5*10^5 5?105
1 ≤ 1\leq 1颜色 ≤ 1 0 6 \leq10^6 106
0 ≤ 0\leq 0糖果数 ≤ 1 0 6 \leq10^6 106

传送

传送

题解

d p [ i ] dp[i] dp[i]表示前i个箱子装完的最小代价,令 l m a x [ i ] l_{max}[i] lmax?[i]表示最左边的一个位置,使得这个位置到 i i i都没有重复的颜色。那么有一个比较显然的dp方程 d p [ i ] = m i n d p [ j ? 1 ] + o r ( i , j ) ( l m a x [ i ] ≤ j ≤ i ? 1 ) dp[i]=min \ dp[j-1]+or(i,j) \ \ \ \ \ \ (l_{max}[i]\leq j\leq i-1) dp[i]=min dp[j?1]+or(i,j)      (lmax?[i]ji?1)
o r ( i , j ) = a i o r a i + 1 o r ? ? ? o r a j or(i,j)=a_i \ or\ a_{i+1}\ or\ ···\ or\ a_j or(i,j)=ai? or ai+1? or ??? or aj?
然后显然时间复杂度是 O ( n 2 ) O(n^2) O(n2)的,考虑优化。

方法一

区间 m i n min min,上线段树。

然后就是从左往右遍历的时候这个 o r or or函数非常不好搞,按位拆开的话,总和的 m i n min min又不好求,但是我们发现我们始终维护的是一些右端点为 i i i的区间,这意味着,如果在 i i i之前有一个 a j a_j aj?的第 b b b个二进制位是 1 1 1,那么 o r ( 1 , i ) , o r ( 2 , i ) , ? ? ? , o r ( j , i ) or(1,i),or(2,i),···,or(j,i) or(1,i),or(2,i),???,or(j,i)的第b个二进制位都是1,所以我们枚举当前糖果数量 V i V_i Vi?的是1的二进制位,预处理 p r e [ i ] [ j ] pre[i][j] pre[i][j]表示i位置前最近的,第j个二进制位是1的数的位置,这个数组 O ( n log ? V i ) O(n\log V_i) O(nlogVi?)就可以处理完毕。然后我们就在线段树上的 [ p r e [ i ] [ b ] , i ] [pre[i][b],i] [pre[i][b],i]这个区间加上 2 b 2^b 2b,就可以实现维护。剩下的就很简单了,区间修改,区间查询最小值。时间复杂度 O ( n log ? n log ? V i ) O(n\log n\log V_i) O(nlognlogVi?)

方法二

同样聚焦于这个or函数,因为or只有区间合并性,没有区间可减性,所以不能用前缀和,用st表 O ( n log ? n ) O(n\log n) O(nlogn)预处理之后可以做到 O ( 1 ) O(1) O(1)计算 o r ( i , j ) or(i,j) or(i,j)。其次,考虑那一长串的or值 o r ( 1 , i ) , o r ( 2 , i ) , ? ? ? or(1,i),or(2,i),··· or(1,i),or(2,i),???其实不同的or值最多只有 O ( log ? V i ) O(\log V_i) O(logVi?)种,而如果 [ a , b ] [a,b] [a,b]这段区间的or值相同,那么我肯定取a转移是更优的。所以我做这么多次二分,找出那 log ? V i \log V_i logVi?个可转移的点,然后转移就行了。时间复杂度也是 O ( n log ? n log ? V i ) O(n\log n\log V_i) O(nlognlogVi?)

  相关解决方案