• 模拟8 题解


    A. 匹配

    $Hash$直接搞。

    如果使用$KMP$,注意B字符串与A完全匹配,这是原本的$KMP$无法处理的问题。

    B. 回家

    刚开始以为是割点,打完后仔细一想发现不对。

    于是打了圆方树,没有什么技巧。

    另一种简单的做法:

    只判断割点,但修改判断割点的方法。

     1 void tarjan(int x)
     2 {
     3     int son=0;
     4     dfn[x]=low[x]=++num;
     5     for(register int i=fr[x];i;i=mo[i].pr)
     6     {
     7         register int y=mo[i].to;
     8         if(!dfn[y])
     9         {
    10             tarjan(y);
    11             low[x]=min(low[x],low[y]);
    12             if(low[y]>=dfn[x]&&dfn[y]<=dfn[n])
    13             {
    14                 son++;
    15                 if(x!=1||son>1) cut[x]=1;
    16             }
    17         }
    18         else low[x]=min(low[x],dfn[y]);
    19     }
    20 }
    来自starsing

    C. 寿司

    断环成链,即把1~n-1补充在长度为n的字符串后。

    将问题中的R和B转化为0和1,

    问题转化为取一个长度为n的区间,移动1,使全部1分布在区间的左右两侧。

    不难发现1每次都应与0交换,才能保证结果最优。

    如果1向左移,移动的距离 等于 与左端点的距离 减去 两者中间1的个数。

    利用前缀和优化,于是能推出$O(1)$计算的式子。

    可以$O(n^2)$枚举区间和1左移右移的分界线,取最小值。

    关于优化枚举的过程:

    不难想到对于每个区间,函数值对于分界线是单谷的。(证明略去,可以参考O(n)正解的证明)

    使用三分法求单峰函数极值即可。

    注意在整数域上,三分法只能将极值收缩到长度不超过3的区间,都应尝试更新。

    复杂度$O(nlogn)$ 常数稍大。

    又发现随着区间的右移,最优决策点是单调不左移的。

    而且最优决策点是一个定值,设区间内0的个数为t,

    如果t为奇数,最优决策点在中位0的左右。

    如果t为偶数,最优决策点在中位两个0左右。

    证明:(大神yxs

    每个1的 向两侧移动的距离 等同于 1与左右端点之间 0的个数。

    对于每一个1,当它在中位0左侧,去左端点更优,

    反之则去右端点更优。

    因为区间中0的总个数不变。

    当区间右移,

    如果原左端点为1,中位0不变。

    如果原左端点为0,中位0右移。

    故中位0单调变化,以一个指针记录中位0的位置,用$while$判断是否右移即可。

    不断更新答案,总复杂度$O(n)$

  • 相关阅读:
    Maven配置--《maven实战》读书笔记
    设置定时任务
    C#中的==
    C# lock的应用
    JDK和JRE
    末尾不以.OK文件结尾的正则表达式匹配
    ftp访问空目录的返回
    正则表达式的结尾匹配
    匿名对象和匿名类
    匿名内部类的调用
  • 原文地址:https://www.cnblogs.com/skyh/p/11246385.html
Copyright © 2020-2023  润新知