zoukankan      html  css  js  c++  java
  • ZJOI2019 minmax 搜索

    给定一棵有根树 (T),根节点深度为 (1),每个节点的深度为其父亲的深度 (+1),每个叶子节点的权值为其编号,现定义每个非叶节点的权值:

    • 对于深度为奇数的非叶节点,其权值为其子节点的权值最大值。
    • 对于深度为偶数的非叶节点,其权值为其子节点的权值最小值。

    然后我们得到根节点的权值 (W)

    对于一个叶子节点的集合 (S),我们现给集合 (S) 的点分配一个新权值 (w_i) 后,使得按照上述规则计算中 (W) 的权值改变,定义这个分配 (w_i) 的方案的权值为 (max_{iin S}|i-w_i|)(w(S)) 为所有方案中最小的权值。

    设叶子节点数为 (m),对于所有的 (2^m-1) 个叶子节点集合,设 (f(k)) 为有多少个集合满足 (w(S)=k),给定 (L,R),求 (f(L)+f(L+1)+...+f(R))

    答案对 (998244353) 取模。

    ( m Sol:)

    嘴巴 AC 一下...代码枯了

    观察到答案要么变大要么变小。

    如果答案要变小,那么我们肯定是将集合内所有元素都减去 (k)

    然后统计有多少个集合可以使得答案变化。

    不难发现我们求的大概是 (sum f(x)[xle k]),设为 (g(k)),差分一下就可以得到答案了。

    但是 (g(k)) 直接求不太好求,因为实际上我们可以求出来的是有多少个集合满足变小后合法,变大后合法,存在一些集合满足变大/变小都合法。

    他们是要减去的。

    事实上那些集合满足变大/变小均合法也很好算,Dp 的时候维护 (4) 个数组就可以了 (f_{u,0/1,0/1}) 表示变大的情况下大于/小于,变小的情况下大于/小于。

    于是就得到了一个 (mathcal O((R-L)cdot n)) 的算法。

    具体 check 大概是对于某个 (k),对于变小的情况,假设 (i-k<W),那么设为 (0),否则设为 (1),那么取 (min) 就是按位 (&),取 (max) 就是按位或,大于的情况同理。

    进一步优化就考虑直接维护 (mathcal O(n)) 个数组,设 (f_{u,0/1,0/1,k}) 表示对于 (k),考虑到点 (u)((0/1, 0/1)) 情况下的答案。

    不难发现转移其实是将数组对应部分乘起来并做加法的过程。

    初始值也是插入在某个状态的一段区间内。

    用线段树合并维护即可,要维护加法标记和乘法标记,复杂度 (mathcal O(nlog n)),空间复杂度 (mathcal O(nlog n)),会附带 (4) 的常数。

    代码枯了。

  • 相关阅读:
    [Codeforces 1214A]Optimal Currency Exchange(贪心)
    [Codeforces 1214D]Treasure Island(dfs)
    [BZOJ 3512]DZY Loves Math IV(杜教筛)
    [BZOJ 3930] [CQOI 2015]选数(莫比乌斯反演+杜教筛)
    [BZOJ 2154]Crash的数字表格(莫比乌斯反演)
    【莫比乌斯反演+分块】BZOJ1101-[POI2007]Zap
    【状态压缩DP】BZOJ1087-[SCOI2005]互不侵犯King
    【概率DP】BZOJ4318-OSU!
    【最大权闭合子图/最小割】BZOJ3438-小M的作物【待填】
    【莫比乌斯反演】HDU1695_GCD
  • 原文地址:https://www.cnblogs.com/Soulist/p/13638263.html
Copyright © 2011-2022 走看看