数据结构1系列题解前瞻
B. 三元上升子序列
算法:线段树、树状数组、分块、(CDQ分治?)
二维偏序板子,开发空间极大,想怎么写就怎么写。
C. STEP
算法:线段树、分块
线段树维护子区间信息板子,类比山海经,由于时限不严,分块也可写。
D. 普通平衡树(数据加强版)
算法:平衡树
平衡树板子,Coner Case较多,比如找完前驱要Splay一下。数据加强可以更好检验算法的正确性。
E. Grass Planting G
算法:树链剖分+线段树
算是树剖板子了吧,由于树剖维护的是点信息,所以需要边权转点权。注意询问的两个点一定相邻。
G. Promotion Counting P
算法:dfs+线段树合并(+离散化?)
线段树合并板子题,对每一个点开一个权值线段树,对于父亲节点直接把儿子的线段树合并过来即可,需要动态开点,可以不离散化和回收节点。
A. 线段树分裂
算法:线段树、(平衡树?)
板子题,不多做评价。但是开发空间很大,我的写法在洛谷题解上没找到,导致当时想贺题解没贺成。
J. Physical Education Lessons
算法:线段树+离散化、线段树+动态开点、珂朵莉树、(分块+离散化?)
注意到区间赋值,于是想到珂朵莉树,所以这题就成了珂朵莉树板子。注意由于CF大佬的Hack,答案需要在修改时预处理出来,以达到 \(O(1)\) 的查询复杂度。当然,这种题目理论上线段树和分块写写也能过,但是不如珂朵莉树好写。
F. 轻重边
算法:树链剖分+线段树
树剖还是板子,但是线段树维护比较复杂。边权转点权这步不变,对于不同次的重边染上不同的颜色,合并时如果两个儿子的合并边界颜色不同则证明中间有条边是“重转轻”,减去答案即可。
H. History
算法:主席树、操作树+线段树
比较离谱的trick。正常树剖是在dfs序上开线段树,本题需要在bfs序上开线段树,由于同一深度的节点bfs差越大距离越远,有单调性,可以二分找到查询的答案。注意二分这里有不少Coner Case,比较难调。回溯用主席树或操作树都行。
W. 基站选址
算法:动态规划+线段树
线段树优化dp,尝试设计状态,设 \(dp[i][j]\) 表示考虑了前 \(i\) 个村庄已经放了 \(j\) 个基站且这个位置放基站的最小花费,则有 \(dp[i][j]=min(dp[k][j-1]+calc(k,i)),k\in[1,i-1]\)。由于有取min且转移和 \(i\) 的位置有关,考虑使用线段树优化,把 \(calc(k,i)\) 拆开,对一个位置预处理能覆盖它的第一个和最后一个村庄,然后根据 \(i\) 判断修改和查询的区间。注意dp数组存的不是最终答案,另外还要把 \(j\) 提到第一层循环。
K. Points
算法:线段树+set(线段树+平衡树?)
典型二维偏序,数据范围过大,需要离散化。动态开点会MLE。注意到询问对 \(x,y\) 的考虑有绝对的优先性,所以在 \(x\) 轴上开线段树,维护区间最大值,另外对每个位置开个set。修改直接做,查询在线段树上找到 \(x\),在对应set里找到 \(y\) 即可。
M. array-value
算法:Trie树+二分
看到序列异或想到Trie树,但是这个东西好像不是很好维护。注意到答案具有单调性,尝试转化为二分,check 一个 mid,返回子区间权值 \(\le mid\) 的区间个数是否有 \(k\) 个。再注意到对于一个端点 \(r\),合法的 \(l\) 是单调分布的,于是只考虑找到当前值的最大合法 \(l\),再去和之前的合法 \(l\) 取 max。复杂度 \(O(n\log V^2)\),\(V\) 为值域大小。