20230721巴蜀暑期集训测试总结
T1
似乎想复杂了。搓了一个 \(O(Q\sqrt{n\log n})\) 的做法,成功跳过正解。结果考后发现普通分块就可以 \(O(Q\sqrt n)\)。而且似乎还 WA 了一些点。
根据题意可以发现 \(b_i\) 为 \(1\) 当且仅当 \(i\) 在二进制下有奇数个 \(1\)。这个可以用来快速求 \(b_i\)。
再观察性质,发现 \(b\) 的构成可以看成初始有一个 \(0\),然后不断将自身取反的结果接到后面。如:
所以 \(b\) 可以看成是若干个长度为 \(2\) 的整数次幂的串正反拼接起来的。那么考虑将这个长度固定,假设为 \(B=2^k\)。
记录一个 \(f_{i}\) 表示 \(a\) 中区间 \([i,i+B-1]\) 与 \(b\) 中区间 \([0,B-1]\) 有多少个不同的位置。反串直接用长度减去即可。
对于修改操作,每次只会影响 \(f\) 中的 \(B\) 个位置,暴力处理单次复杂度 \(O(B)\)。对于查询操作,开头的整块直接用 \(f\) 数组统计答案,单次复杂度 \(O(\frac nB)\),末尾散块暴力计算,单次复杂度 \(O(B)\)。\(B\) 取最靠近 \(\sqrt n\) 的 \(2\) 的整次幂。复杂度 \(O(Q\sqrt n)\)。
T2
时间不太够,\(30pts\) 暴力都没有调出来。此题直接爆 \(0\)。这个正解感觉也不是太难,但还是需要一些时间冷静思考的,但是赛时时间剩的不多就不敢想太深了,生怕陷进去导致暴力没时间打。
\(4\) 个变量,不能枚举,考虑逐一确定。
先考虑 \(k\) 的限制。将问题放到二维平面上,有点 \((i,a_i)\)。扫描线从下往上扫,将扫到的点作为 \(d\),它会对右边扫到过的点作为 \(l\) 的方案产生 \(1\) 的贡献代表多了一种 \(d\) 的选择。然后这些 \(l\) 会对右边未扫到的点作为 \(r\) 的方案产生 \(1\) 贡献。最后枚举 \(u\) 来计算答案。最终统计每个 \([1,k]\) 中的 \(u\) 的答案。
考虑将中转的 \(l\) 跳过,让 \(d\) 直接对 \(r\) 产生贡献,那么贡献为横坐标在 \(d\) 和 \(r\) 之间且被扫到过的点数。
那么如何计算这个点数呢?观察发现它可以表示为 \(cnt_r-cnt_{d-1}\) 的形式,其中 \(cnt_x\) 表示扫到过的横坐标小于 \(x\) 的点数。
\(cnt_{d-1}\) 每次可以直接区间加,但 \(cnt_r\) 是会变化的。再观察一下发现每次 \(cnt_r\) 会被加入 \(r\) 的贡献,然后 \(cnt_r\) 自己会 \(+1\)。所以最终会对 \(r\) 贡献一个等差数列和,最后再加入即可。
最终时间复杂度 \(O(n\log n)\)。
T3
当时一看到询问操作序列区间就直接懵了,甚至还要操作序列区间修改,就是本能抵触,也没想到去分析一些性质转化问题啥的。好在最低档暴力还是比较好打的,没用多久拿了 \(20pts\)。但其实最后打 T2T3 的时候就已经只剩 1h 出头,主要就是前面思考三道题和 \(T1\) 调 + 卡常用了很多时间。
可以观察到几个性质:
-
每个弹出操作对应的压入操作是固定的,可以通过括号序列确定。
-
一个压入操作只会被之前相邻的一段连续弹出操作影响。故可以从他们对应的压入操作向这个压入操作连边形成一棵树(根为 \(n+1\))。染蓝色的过程就是对于每一个蓝色点,将它到根的路径上所有点染成蓝色。
-
连边不会交叉。也就是不存在两条边 \((a,b),(c,d)\) 满足 \(a<c\) 且 \(c<b<d\)。
由于连边不会交叉,所以一段区间的 dfs 序是连续的。考虑如果询问区间是连通的,那么答案就是蓝点构成虚树的大小。那么如果不连通,考虑加一条从 \(dfn_u=dfn_l-1\) 的点 \(u\) 到根链将他们串起来最后再减去 \(u\) 的贡献。
可以线段树维护区间内蓝点以及相邻蓝点 LCA 到根的距离。