zoukankan      html  css  js  c++  java
  • 【做题记录】数据结构

    二分答案,设为 (mid),把小于 (mid) 的数设为 (0),大于等于 (mid) 的数设为 (1)

    然后就很好排序了,查询 ([l,r])(1) 的个数(即区间和),升序则把 (0) 填区间左边,(1) 填右边,降序则相反。

    最后如果 (q) 位置的数为 (1),说明答案至少为 (mid)

    因数个数 (=) 各质因子次数 (+1) 之积。

    小于 (sqrt[3]{x}) 的质因子直接用前缀和搞掉。大于 (sqrt[3]{x}) 的质因子最多有两个,这些用 Miller-rabin + 二分处理出来,再离散化(并不需要 PR)。然后上莫队即可。

    分块。设块长为 (T)。对每个块维护一个排好序的数组 (b)

    修改时,整块直接打上标记。对于散块,直接加再排序并不优秀。在原数组中修改后,将 (b) 按是否要修改分成两队,发现它们各自仍是有序的。二路归并即可。

    查询时,二分答案,查询小于答案的数的个数。对于整块,在 (b) 中二分。对于左右两个散块,暴力统计并不优秀。在 (b) 中把两个散块要查询的部分取出,再归并起来,就可以二分了。

    时间复杂度 (O(qdfrac{n}{T}log^2n+qT))(T=sqrt{n}log n) 时最优,为 (O(qsqrt{n}log n))

    二分答案。设为 (mid)。把小于 (mid) 的数设为 (-1),大于等于
    (mid) 的数设为 (1)

    如果一段区间的和 (ge 0),说明其中位数至少为 (mid)

    要判断是否存在一个子区间满足这个条件,考虑让区间和最大,即 ([b+1,c-1]) 的和 (+;[a,b]) 的最大右子段和 (+;[c,d]) 的最大左子段和。

    用主席树即可。

    首先离散化,注意不要去重。

    对于每个区间,用莫队维护 bitset 表示数的出现情况。考虑将多个相同的数分开,如果一个数 (x),出现了第 (b[x]) 次,给它一个标号 (x+b[x]-1),删除同理。这样就可以把相同的数字集中在值域上以 (x) 为左端点的区间内。由于离散化时没有去重,不同数字间互不干扰。最后用三个区间的总长,减去它们对应的 bitset 按位与的结果中 (1) 的个数 ( imes 3) 即可。

    小技巧:把询问分成 (10) 组,防止 MLE。

    先考虑序列上的做法。设 (f(x,y)) 表示 ([1,x])([1,y]) 的答案。那么 ([l,r]) 的答案可表示成 (f(r,r)-f(l-1,r)-f(l,r-1)+f(l-1,l-1))。然后就可以莫队 / 分块了。

    现在到了树上,还有换根,无非就是多了 dfs 序、分类讨论和倍增。

    还是用 bitset。维护正反两个 bitset,表示每个数的出现情况(对于 (x),把它放在 b1(x) 处和 b2(M-x) 处,(M) 表示值域)。

    加法:若 (a+b=x),则 (a=x-b=x-(M-b^prime)=b^prime-(M-x)),即 b1&(b2>>(M-x))

    减法:b1&(b1>>x)

    乘法:暴力枚举因数

    除法:若 (x>sqrt M),枚举 (a),检查 (a)(ax) 是否都存在;否则,预处理出 (pos_{i,k}),表示 ([1,i]) 内最大的 (j),满足 (a_j imes k=a_i)(a_i imes k=a_j),并对每个 (k) 做前缀最大值。查询时判断 (pos_{r,x}) 是否 (ge l)

    发现 1 和3 操作可以分为父亲和儿子,而父亲很好处理。

    对于每个节点,将其所有儿子的权值放到一个 trie 里,并从低位开始(因为要支持加 (1))。再维护每位上有几个 (1)和一个加法标记。

    考虑二进制加法:找到最右边的 (0),把它右边的 (1)全部变成 (0),并把这个 (0) 变成 (1)。对应到 trie 树上就是:交换两个儿子,并往现在的 (0) 子树走(过去的 (1) 子树)。

    单点修改其实就是在父亲的 trie 中删除再插入。

    用 LCT 维护链上最小值(以边的编号为权值),即最大生成树。

    加入边 (i) 时,若两点已联通,设两点路径上的最小编号为 (p_i)。对于一次询问,考虑一种使编号小的边尽可能被使用,并构成森林的策略选边。如果 (p_ige l),由于 (p_i) 是路径上的最小编号,路径上的所有边都会出现,边 (i) 也就没用了。反之,就要把 (i) 加入森林。所以询问其实是求 ([l,r])(p_i<l) 的数量,用主席树维护。答案就是点数 (-) 边数。

    朴素做法:对每个数开一个 vector,按顺序存储值为这个数的下标。预处理出 (l..r) 块的答案,枚举散块的每个数,二分出出现次数并和整块的答案比较。

    但复杂度是 (O(nsqrt{qlog n})),不够优秀。

    记录一个 (t_i) 表示 (i)(a_i) 的 vector 中的位置。

    枚举散块每个位置 (i),设当前答案为 (ans),若 (a_i) 的 vector 中第 (t_i+ans) 个数仍不超过 (r),说明 (a_i) 更优。然后一直加 (ans) 直到 vector 中第 (t_i+ans) 个数超过 (r) 或不存在。

    复杂度证明:设整块答案为 (ans),那么实际答案一定不超过 (ans+2T),也就是 (ans) 最多加 (2T) 次。

    分块 + ST 表。

    设块长为 (T),记录每块最大值,块内的前、后缀最大值,并对整块构建 ST 表。

    若区间横跨多个块 (T),可以 (O(1)) 求得答案。否则可以暴力,由于数据随机,这些区间的概率为 (dfrac{T}{n})

    时间复杂度 (O(q+dfrac{qT^2}{n}+dfrac{n}{T}log n)),取 (T=log n) 最优,为 (O(n+q))

    莫队二次离线,用值域分块平衡最后查询的复杂度。

    堆优 Dijkstra + 主席树

    二进制下,加上 (2^k),其实就是从第 (k) 位往高位找到第一个 (0),把它改为 (1),并把这个 (0)(k) 的所有 (1) 改成 (0)

    只有两次修改,可以上主席树。

    比较大小可以用哈希,先判断高位子树是否相等,相等则往低位子树走,否则往高位子树走。

    有一个 弱化版

    考虑在树上把 (dep^k) 做差分,即 (v_u=dep_u^k-(dep_u-1)^k)

    对于 (x,y),把 (1)(y) 路径上所有点的点权设为该点的 (v),其他点点权为 (0)。令 (z=LCA(x,y)),那么 (1)(x) 路径上的点权和就是 (1)(z) 的点权和,即 (dep_z^k)

    把询问按 (x) 排序,就变成了路径修改、路径求和的问题,即:

    维护一个数组 (b),初始为 (0)

    1. (1)(x) 上的所有点 (i)(b_ileftarrow b_i+v_i)

    2. 求路径上 (b_i) 的和。

    树剖 + 线段树实现。

    对于非叶子节点,设左右子树和整棵子树选到 (x) 的概率分别是 (L_x,R_x,F_x)

    (F_x=p(L_xsumlimits_{i<x}R_i+R_xsumlimits_{i<x}L_i)+(1-p)(L_xsumlimits_{i>x}R_i+R_xsumlimits_{i>x}L_i))

    用线段树合并优化,递归时维护两个标记表示两棵树分别要乘多少。

    分块。区间第 (k) 小考虑值域分块。

    对于每个块,用并查集把值相同的下标合并(从大的下标指向小的下标),并记录每个数的根。这样我们只需要保证根是真正的值。整块修改时判断是否已经有了 (y),如果有了就把 (x)(y) 合并起来,并把根的值改为 (y)。散块暴力重构。

    设区间长度为 (L),对于一个数 (x),如果它出现了 (k) 次,贡献为 (x imes) 包含 (x) 的子序列个数,即 (x(2^L-2^{L-k}))

    考虑莫队 + 根号分治。预处理出出现次数 (>sqrt n) 的数,每次询问暴力枚举这些数计算贡献。对于其他数,令 (sum_i) 为出现了 (i) 次的数之和(注意不要取模,每次模数会变化)。枚举出现次数,计算这些数的贡献。

    用光速幂即可消去一个 (log)

    发现 (3,4,5,6) 操作其实是对连续极长 (0,1) 段的两端点进行修改。可以用平衡树维护这些极长段。但有可能修改产生了长度为 (0) 的段,可以维护最小区间长度,判断是否存在,暴力删除。

    可以分开维护(标记处理较方便),也可以一起维护(推平较方便)。

    分块。对于每个块,都对颜色进行一次重标号(离散化),并预处理出每块内两两颜色的最小距离、每个颜色最左 / 右的位置。

    整块修改时,如果 (y) 没有出现,直接修改标号,距离并不会变化。如果出现了,暴力修改原数组,更新一下距离。散块暴力重构。

    复杂度分析:整块修改时,如果 (y) 出现了,必会导致颜色数减 (1),最多减 (sqrt{n}) 次,每次都遍历整个块,这一部分复杂度 (O(nsqrt{n}))

    而散块修改最多使两个块颜色增加,这一部分 (O(qsqrt{n}))

  • 相关阅读:
    Oracle 与.NET Framework 数据类型映射
    mvc使用JsonResult返回Json数据(转)
    like参数替换
    jquery 等比缩放
    【linq to sql】已有打开的与此命令相关联的 DataReader,必须首先将它关闭
    脚本
    2012年计划——开始我的敏捷个人之行
    在Win7 64位机器上安装Oracle 10客户端以及PlSql
    词干提取算法Porter Stemming Algorithm解读
    开源搜索框架Lucene学习之分词器(2)——TokenFilter类及其子类
  • 原文地址:https://www.cnblogs.com/creating-2007/p/14950571.html
Copyright © 2011-2022 走看看