写大分块写的。

难度升序排列。

[Ynoi2017] 由乃打扑克

梦开始的地方。

对块内排序,二分查找。

\(O(n\sqrt {n\log n+\Delta })\)

[Ynoi2011] 初始化

根号分治板子。就是卡常。

大于 \(B\) 的直接加,小于 \(B\) 的显然可以记 \(f_{i,j}\) 表示所有模 \(i\)\(j\) 的位置加的数。发现这样算的话修改和查询分别是 \(O(1)-O(B)\) 的,所以考虑记 \(pre_{i,j}\) 表示模 \(i\)\(j\) 的贡献,\(suf_{i,j}\) 表示模 \(i\)\(j\sim i\) 的贡献。这样就变成 \(O(B)-O(1)\) 了。对每个 \(i\) 算算贡献即可。

代码不难写,但是 |x| 卡常。

结果我定义 fread fwrite 数组和开大了 pre 和 suf 导致多开了约 1e7 个 char,开着开着 TLE 了。综上所述,fread 不如普通快读。/cf

P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I.

考虑分块。

我们发现一段区间的贡献可以拆为整块对整块、散块对散块、散块对整块。

所以考虑预处理 \(ans_{i,j}\) 表示 \(i\sim j\) 块的贡献,\(sum1_{i},sum2_{i}\) 分别表示块首/块尾到第 \(i\) 个数的贡献,\(f_{i,j}\) 表示前 \(i\) 个数对第 \(j\) 个块的逆序对贡献。设 \(calc(a,b,c,d)\) 表示区间 \([a,b]\) 和区间 \([c,d]\) 的贡献。

则对左右端点在同一块内的情况,答案为 \(sum1_r-sum2_l-calc(l,r,L_{Bl},l-1)\)

对于左右端点不在同一块的情况,答案为 \(ans_{Bl+1,Br-1}+sum1_r+sum2_l+calc(l,R_{Bl},L_{Br},r)\sum\limits_{i=bl+1}^{br-1}(f_{i,(l\to R_{bl})}+f_{i,(L_{br},r)})\)

接下来考虑预处理贡献。

对于 \(calc\),显然可以预处理出块内有序数组之后归并。

对于 \(sum1_i,sum2_i\),可以直接在块内用树状数组计算贡献,这部分是 \(O(n\log n)\) 的。

对于 \(f\),对整个序列排序,发现从小到大插入后每个位置的贡献可算,复杂度为 \(O(n\sqrt n)\)

对于 \(ans\)\(ans_{i,j}=ans_{i+1,j}+ans_{i,j-1}-ans_{i+1,j-1}+f_{j,R_i}-f_{j,L_i-1}\)

于是就做完了。

发现写的很降智。

降智错误:

  1. 归并排序把两个数组放进一个了。

  2. 块个数 \((n-1)/sz+1 -> n/sz\)

  3. 使用宏定义使得过慢。

[Ynoi2019 模拟赛] Yuno loves sqrt technology III

\(f_{i,j}\) 表示 \(i\sim j\) 的块的答案,这个可以直接做。

\(pos_x\) 表示所有 \(x\) 出现位置。

然后对于散块的每个位置,查询他在 \(pos_x\)\(+/-ans\) 的位置是否 \(\le r \ or \ge l\),如果是则 \(ans++\)。显然每次 \(ans\) 只会增加 \(O(\sqrt n)\) 次。

怎么有傻逼强制在线不异或 \(lans\) 的。

[Ynoi2016] 镜中的昆虫

正解是 cdq 分治,但是我们考虑分块!

容易想到一个经典套路:在数颜色的时候只数这个区间里某种颜色最右(左)边的点 。具体地说,我们维护一个 nxt 数组表示下一个和 \(a_i\) 的值相同的数的位置,如果没有 \(nxt_i=n+1\)。那么显然问题转化为求 \([l,r]\)\(nxt_i>r\)\(i\) 的数量。单点修改时,我们可以维护一颗珂朵莉树,二分找第一个和当前位置颜色相同的点即可。这显然是一个带修改的二维数点问题,cdq 分治、树套树、分块套分块维护皆可。

显然这可以经典根号平衡。

我们可以序列分块套值域分块。序列分块要求单点修改,整体查询 \(nxt\)\(<=r\) 的个数。显然可以再套一个值域分块,维护块内前缀和。因为单点修改 \(O(1)\),因此值域分块可以采用 \(O(\sqrt n) - O(1)\) 的方式,就可以平衡复杂度做到 \(O(n\sqrt n)\) 了。

LOJ 上过了,但是 luogu 机子慢。

posted @ 2024-02-29 08:41  lgh_2009  阅读(4)  评论(0编辑  收藏  举报