20201007day29 模拟(九)
24赛高~
szq、gjz是神!
话说题目难度不应该是3412么?
1
problem
给定\(n\)个节点的以1为根的有根树,初始点权为1.对于每次操作\(i\),修改一个以\(u_i\)为根的子树内所有节点权值为0,询问所有次询问所得答案的异或和。
solution
做法一
按照 \(O(n^2)\) 的暴力做法,每次修改暴力递归子树统计,标记每一个访问到的节点,如果遇到访问过的节点,说明该节点的整棵子树都已经被标记过了,可以直接返回。可以证明这样做的复杂度是 \(O(n+m)\) 的。
做法二
相当于每次对dfs序一个区间染色,可以用并查集实现,即把相邻的已被染色的位置连到一个联通块内, 时间复杂度为\(O(n\alpha(n))\)或\(O(n\log n)\),实际效率和做法一差不多。
code
2
problem
给定一棵树,每次询问点\(u\),回答:
solution
可以交换求和顺序,询问\(u\)就相当于考虑以\(u\)为根时每个点\(x\)的子树内有多少个点的\(w\)小于该点,记这个值为\(h_x\),答案为所有\(h_i\)的总和。
先考虑如何求\(u=1\)时的答案,以\(1\)为根dfs,同时维护一个数据结构用来查询到根路径上有多少个点的\(a_i\)大于当前点。
然后通过换根dp求出每个\(u\)的答案,可以发现当根从点\(x\)变为\(x\)的儿子\(y\)时,\(y\)的子树会变为所有点,\(x\)的子树会变为不“在以\(1\)为根时\(y\)子树内”的所有点。
此做法时间复杂度\(O(n\log n)\)。
code
3
problem
给定以\(\text{A,B,C}\)构成的字符串\(s\),两种操作:
1 p X
:表示\(s[p]\)修改为X
2 l r
:求\([l,r]\)子串的本质不同子序列个数(不含空序列)。
串\(R\)是串\(T\)的子序列当且仅当串\(R\)可以通过删去\(T\)中的某些字符得到。
两个子序列本质不同当且仅当它们长度不同或存在一个位置使得该位置上两个子序列的字符不同。
solution
首先对于没有修改的情况,有一个显然的 \(dp\) 转移:
if(!last[i]) dp[i] = dp[i - 1] * 2 + 1;
if(last[i]) dp[i] = dp[i - 1] * 2 - dp[last[i] - 1];
其中 dp[i]
表示考虑前 \(i\) 位的方案数,last[i]
表示最近的与 a[i]
相同的字符的位置,如果 a[i]
第一次出现,则 last[i]
为 \(0\)
现在我们考虑矩阵。
设状态矩阵 \(A\),其中 A[i][j]
表示以 \(i\) 开头,在结尾预支一个 \(j\) 的方案数,其中 \(i,j\) 为 \(0\) 时表示一个空序列。
对于一个数 \(i\) 的初始矩阵,对于对角线的元素,显然方案数为 \(1\),而对于第 \(i\) 行,显然都为 \(1\)。
比如对于数字 \(1\) 的初始矩阵为 \(\begin{bmatrix} 1\ 0\ 0\ 0\\ 1\ 1\ 1\ 1\\ 0\ 0\ 1\ 0\\ 0\ 0\ 0\ 1\\ \end{bmatrix}\)。
容易发现两个状态矩阵的合并就是矩阵乘法,即 \(C_{i,j}=\sum\limits_{k=0}^3A_{i,k}\times B_{k,j}\)
用线段树支持查询和修改即可,时间复杂度\(O(4^3 m\log n)\)。
code
4
problem
给定长为\(n\)的正整数序列,每次选择连续的\([L,R]\)序列使其-1
,每次的贡献为\((R-L+1)^2\)。现想使其全部变为0,且每次选择的区间内不得有0(即\(\forall i\in[L_x,R_x],a[i]\neq 0\))。求在操作次数最少情况下的操作次数,贡献最小值和贡献最大值。对\(10^9+7\)取模。
solution
先令\(b_i=d_i-d_{i-1}\) 那么我们相当于每次选取\(l<r\),令\(b_l-1\),\(b_r+1\),代价\((r-l)^2\),令所有\(b\)变成\(0\)。
容易发现最短时间为\(\sum_i max(b_i,0)\),达到最短时间需要我们每次每次选择的\(b_l>0\),\(b_r<0\)。
考虑一种贪心策略,遍历\(b_i\),若有\(b_i>0\)将其压入队列中,\(b_i<0\)则
若使得代价最大,与最靠左的\(b_l\)配对。
若使得代价最小,与最靠右的\(b_l\)配对。
注意到\(d_i \geq 0\),所以我们一定能找到数字配对。
可以用交换法证明贪心的正确性。时间复杂度\(O(n)\)。