\[\texttt{T1 改造二叉树}\]
什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树。设 key[p] 表示结点 p 上的数值。对于其中的每个结点 p ,若其存在左孩子 lch,则key[p]>key[lch];若其存在右孩子 rch ,则 key[p]<key[rch];注意,本题中的二叉搜索树应满足对于所有结点,其左子树中的 key 小于当前结点的 key ,其右子树中的 key 大于当前结点的 key 。
小 Y 与他人讨论的内容则是,现在给定一棵二叉树,可以任意修改结点的数值。修改一个结点的数值算作一次修改,且这个结点不能再被修改。若要将其变成一棵二叉搜索树,且任意时刻结点的数值必须是整数 (可以是负整数或 0),所要的最少修改次数。
考虑一个二叉树,可以将其中序遍历以后得到数组 \(num_i\),然后让 \(num_i-i\),求一波最长不下降子序列就可以了。
\[\texttt{T2 数字对}\]
- 她的面前浮现出一个长度为 n 的序列 ai ,她想找出一段区间 L, R (1 <= L <= R <= n)。
这个特殊区间满足,存在一个 k(L <= k <= R) ,并且对于任意的 i (L <= i <= R), ai 都能被 ak 整除。这样的一个特殊区间 L, R 价值为 R - L。
小 H 想知道序列中所有特殊区间的最大价值是多少,而有多少个这样的区间呢?
考虑一个链表存储的是自己的 \(L,R\)而,很显然,如果你的左链表在往左扩展的时候可以这样子 :
\[x=L_x-1\]
同理:
\[y=R_y+1\]
时间复杂度 \(O(N)\) (假设排序是基数?)
\[\texttt{T3 战争游戏}\]
我们考虑一个割点,它肯定是一个必经点。
考虑两种贡献形式:
\[A=\frac {\sum (tot-size_y) \times size_y}{2}\]
\[B=\sum (N-tot-1) \times size_y\]
procedure Tarjan(u,vv:longint);
var
tmp:array[-1..3] of longint;
v,i,tot:longint;
begin
tot:=0; inc(cn); low[u]:=cn; dfn[u]:=low[u]; i:=cnt[u];
while i<>-1 do
begin
v:=reach[i]; ask[v]:=false;
if dfn[v]=0 then
begin
Tarjan(v,u); inc(size[u],size[v]); ask[v]:=true;
if (low[v]>=dfn[u]) then inc(tot,size[v]);
end;
if (v<>vv) then low[u]:=min(low[u],low[v]); i:=next[i];
end;
i:=cnt[u]; tmp[1]:=0; tmp[2]:=0;
while i<>-1 do
begin
if (dfn[u]<=low[reach[i]])and(ask[reach[i]]) then
begin
inc(tmp[1],(tot-size[reach[i]])*size[reach[i]]); inc(tmp[2],(n-tot-1)*size[reach[i]]);
// if(u=1) then writeln(dfn[u],' ',low[reach[i]]);
end; i:=next[i];
end;
tmp[1]:=tmp[1] >> 1;
ans[u]:=tmp[1]+tmp[2]+n-1;
end;
\[\texttt{T4 艰难的选择}\]
- 他让学校的所有人按照身高排成一排,然后从中选出连续的若干个人,使得这些人中男女人数相等。Yzx 当然希望他能选出的人越多越好,请告诉他最多可以选出多少人来。
将女生看作 \(-1\),男生看做 \(1\)。然后前缀和两两匹配的区间 \(num_l=num_r\) 起存在贡献 \(r-(l+1)+1\)。
\[\texttt{T5 人品问题}\]
- yzx 提出的人品计算方法相当简单,只需要将测试对象的 k 个祖先的人品指数 (可能为负数) 加起来即可。选择哪 k 个祖先可以由测试者自己决定,但必须要满足这个要求:如果除自己的父母之外的某个祖先被选了,那么他的下一代必需要选 (不允许跳过某一代选择更远的祖先,否则将失去遗传的意义)。现在 yzx 需要你帮助他找到选择祖先的最优方案,使得他的人品值最大。
考虑一个 shit 上 DP,考虑儿子 \(j-k\) 的选的次数和当下 \(j\) 的选择次数。我们设 \(f_{i,j}\) 代表第 \(i\) 个点选了 \(j\) 次。
\[f_{i,j}=\max \{f_{i,j-k}+f_{son_{i,l},k} \}\]
procedure Dfs(i:longint);
var j,k,l:longint;
begin
for l:=1 to 2 do
begin
if son[i,l]=0 then continue; Dfs(son[i,l]);
for j:=m downto 1 do for k:=1 to j do fuck[i,j]:=max(fuck[i,j],fuck[i,j-k]+fuck[son[i,l],k]);
end;
end;
\[\texttt{T6 回家}\]
moreD 城的城市轨道交通建设终于全部竣工,由于前期规划周密,建成后的轨道交通网络由 2n 条地铁线路构成,组成了一个 n 纵 n 横的交通网。如下图所示,这 2n 条线路每条线路都包含 n 个车站,而每个车站都在一组纵横线路的交汇处。
出于建设成本的考虑,并非每个车站都能够进行站内换乘,能够进行站内换乘的地铁站共有 m 个,在下图中,标上方块标记的车站为换乘车站。已知地铁运行 1 站需要 2 分钟,而站内换乘需要步行 1 分钟。 你的最后一个作业就是算出,在不中途出站的前提下,从学校回家最快需要多少时间 (等车时间忽略不计)。
考虑将每一个点拆成"行点"和"列点",它们连上每一个可以连的点,随后互联 (边权为 \(1\))。可以用排序实现连边,然后跑一波 Dij 就可以了。
\[\texttt{T7 已经没有什么好害怕的了}\]
- 小Y 最近开始学习算法姿势,但是因为小R 非常BB,给了她很多B6 题,所以她觉得自己已经没有什么前途了。于是小R 给了她一些稍微简单的题,让她觉得已经没有什么好害怕的了,其中一道是这样的:
给定一个长度为n 只包含左括号和右括号的序列,现在小R 想要知道经过每一个位置的合法子串有多少个。 - 空串是一个合法的串,如果A 和B 都是合法的串,那么 (A) 和AB 都是合法的串。
死亡 FLAG 大法。
考虑一个右括号的左边是一个左括号的话,那它的贡献可以转移到这个左括号所对应的右括号。按照这个思路搞下去就可以了。
for i:=1 to len do
begin
if (s[i]=')')and(tail<>0) then begin next[stark[tail]]:=i+1; last[i+1]:=stark[tail]; dec(tail); end;
if (s[i]='(') then begin inc(tail); stark[tail]:=i; end;
end;
for i:=len+1 downto 1 do begin inc(plu[i]); inc(plu[last[i]],plu[i]); end;
for i:=1 to len do begin inc(dix[i]); inc(dix[next[i]],dix[i]); end;
for i:=1 to len do fuck[i]:=fuck[i-1]+plu[i]-dix[i];
for i:=1 to len do ans:=ans+((i*fuck[i]) mod 1000000007);
writeln(ans);
\[\texttt{T8 我才不是萝莉控呢}\]
- 有一个长度为n 的正整数数组A,满足Ai >= Ai+1,现在构造一个数组B,令Bi = \(\sum\limits^{n}_{j=i} a_j\)。
现在,有一个n * n 的网格图,左下角坐标是(1, 1),右上角坐标是(n, n)。有一个小SB正在坐标为(n, 1) 的位置,每一时刻,如果他现在在(x, y),他可以选择走到(x ????-1,y + 1) 或者(x, (y + 1) div 2),如果选择后者,他要支付Bx的代价。
现在他想走到(1, 1),你可以告诉他他支付的代价最少是多少吗?注意在任何时候他都不能离开这个网格图。
考虑一个图的贡献,然后对原数组进行合并果子。
显然 WAY2 是最优的,那么这是一个合并果子的结果,以为保证了 \(a_i\) 的升序列。
\[\texttt{T9 寻找神格}\]
- 第一行包含两个正整数N,Q,表示部落数和神格的信息数与询问数总和。
- 第二行包含N个数,第i个数a_i表示编号为i的部落最初的人数。
接下来Q行,第一个数为t。 - 当t=0时,这一行还有两个数a,b,表示编号为a的部落增加了b个人(如果b<0则表示减少了|b|个人)。
- 当t=1时,这一行还有三个数a,b,c,表示编号为a~b的部落增加了c个人(如果c<0则表示减少了|c|个人)。
- 当t=2时,这一行还有两个数a,b,表示神格询问了编号为a~b的部落现在的总人数。
- 当t=3时,这一行还有两个数a,b,表示神格询问了编号为a~b的部落人数的方差。
- 方差的定义:
求N个数的方差,设这N个数的平均数为ave,第i个数为x_i
方差=1/n[(x_1-ave)^2+(x_2-ave)^2+⋯+(x_(n-1)-ave)^2+(x_n-ave)^2]
\[\frac{1}{N} \sum (x_i-ave)^2\]
考虑一个方差的定义,可以分解。由于操作比较多,我们可以考虑用分块或者是珂朵莉树来维护。