JZOJ 集训 B 组选讲

\[\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 战争游戏}\]

5c4af2b755552.png

我们考虑一个割点,它肯定是一个必经点。

考虑两种贡献形式:

5c4af41b4b33f.png

\[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 分钟。 你的最后一个作业就是算出,在不中途出站的前提下,从学校回家最快需要多少时间 (等车时间忽略不计)。

6547.png

考虑将每一个点拆成"行点"和"列点",它们连上每一个可以连的点,随后互联 (边权为 \(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),你可以告诉他他支付的代价最少是多少吗?注意在任何时候他都不能离开这个网格图。

考虑一个图的贡献,然后对原数组进行合并果子。

5c4afc8174875.png

显然 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\]

考虑一个方差的定义,可以分解。由于操作比较多,我们可以考虑用分块或者是珂朵莉树来维护。

转载于:https://www.cnblogs.com/FibonacciHeap/articles/10321480.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值