很容易联想到一种模型:
对于 v i v_i vi相同的操作,有用的最多只有 d ( d ≤ 10 ) d(d\leq 10) d(d≤10)个(相当于按时间戳维护了一个 d i d_i di递减的单调栈)
但每个点向外暴力染色在稠密图上复杂度依旧是 O ( n 2 ) O(n^2) O(n2)的。
需要找到一种方法使得复杂度降到 n d nd nd,考虑被染色点:
发现实际上每个点被染色的操作中只有 d d d个有用的,倒着加操作xjb D F S DFS DFS即可。
字符集 100 100 100, ∣ S ∣ ≤ 200 |S|\leq 200 ∣S∣≤200显然就是每个字符出现两次的倍增构造:
一开始想成 112233... 112233... 112233...然而长度也是 2 n 2^n 2n级别的,真是zz。。。
正解:
设现在前半部分为 X X X,后半部分为 Y Y Y,考虑插入一个未出现的 c c c, c X c Y → a n s × 2 cXcY\to ans\times 2 cXcY→ans×2, c X Y c → a n s + 1 cXYc\to ans+1 cXYc→ans+1(为什么不是 c c X Y ccXY ccXY?形式不优美呀)
非常重要的一条性质(传递性):
若 a , b a,b a,b都能与 c c c交换,那么 a , b a,b a,b也能交换。
所以取出所有能与同色最轻球直接或间接地交换的球(间接就是通过异色最轻球),这些球之间都可以重排,组合数算一下排列。
显然只有 log v \log v logv次跳跃:
把第 i i i次跳跃能互相到达的点连起来,就是一段段区间。预处理 l e f t [ i , j ] , r i g h t [ i , j ] left[i,j],right[i,j] left[i,j],right[i,j]表示点 i i i在已经跳跃 j j j次后能走到的最左/右点。
问题转化为:
钦定第一次跳跃前的区间,剩下每层选一个区间,判断能否覆盖所有点。
假设第一次选择的区间为 [ l , r ] [l,r] [l,r],则需要用剩下 log v \log v logv个操作覆盖 [ 1 , l ) , ( r , n ] [1,l),(r,n] [1,l),(r,n]。
因为可以左右横跳,所以枚举 s s s集合状压DP f [ S ] f[S] f[S]表示 S S S集合中的跳跃可以覆盖的最大的 [ 1 , i ] [1,i] [1,i]的区间, g [ S ] g[S] g[S]表示可以覆盖的最大的 [ j , n ] [j,n] [j,n]区间。
合并处理出 m i i mi_i mii表示用部分集合覆盖 [ 1 , i ] [1,i] [1,i]时,最小的 x x x满足 [ x , n ] [x,n] [x,n]能被完全覆盖。
时间复杂度 O ( n log v ) O(n\log v) O(nlogv)
a i a_i ai排序后得到两个关键性质:
显然 i i i越大, b i b_i bi的限制越多。
考虑倒序 d p [ i ] [ l ] [ r ] dp[i][l][r] dp[i][l][r]表示处理到 b [ i ] b[i] b[i],可选范围中 ≤ b i \leq b_i ≤bi的数有 l l l个, > b i >b_i >bi的数有 r r r个的方案数。
注意细节
代码