首页 > 其他分享 >Middle Duplication (CFD2E) (贪心,中序树,字典序大小.dfs)

Middle Duplication (CFD2E) (贪心,中序树,字典序大小.dfs)

时间:2023-03-08 23:35:32浏览次数:36  
标签:cost int 中序 dfs 复制 CFD2E 节点

 

 大佬的思路:

 

 

#include<bits/stdc++.h>
using namespace std;
int n,k,l[200010],r[200010],pos[200010];
char c[200010];
vector<int>seq;
void precalc(int u)
{
    if(l[u])precalc(l[u]);
    seq.push_back(u);
    if(r[u])precalc(r[u]);
}
bool good[200010],isDup[200010];
void dfs(int u,int cost)
{
    if(!u||cost>k)return;
    dfs(l[u],cost+1);
    if(isDup[l[u]])isDup[u]=1;
    else if(good[u])isDup[u]=1,k-=cost;
    if(isDup[u])dfs(r[u],1);
}
int main()
{
    scanf("%d%d",&n,&k);
    scanf("%s",c+1);
    for(int i=1;i<=n;i++)scanf("%d%d",&l[i],&r[i]);
    precalc(1);
    char lst=c[seq.back()];
    for(int i=n-2;i>=0;i--)
    {
        int u=seq[i],v=seq[i+1];
        if(c[u]!=c[v])lst=c[v];
        if(c[u]<lst)good[u]=1;
    }
    dfs(1,1);
    for(auto u:seq)
    {
        putchar(c[u]);
        if(isDup[u])putchar(c[u]);
    }
    return 0;
}
View Code

后记:

  • 他本身就是要中序后的一个字典序的大小
  • 于是看看中序排序后的序列是什么, 然后根据这个序列看看那个点是不是需要复制 (比后面第一个不同的数小)
  • 在上面预处完后开始dfs, 更具字典序性子
  • 左边优先级最高,然后就是中间吗,在是右边, 
  • 注意这个是更新时的前提时父亲也要加倍, 所以中间不行时,右边一定也不行

题目分析

我们首先进行一次中序遍历,找到每个节点在中序遍历中所处的位置。

接下来,我们能知道每个节点被复制是否会让字典序更小。只需要对比它和在中序遍历中的下一个和它不同的字符的大小即可。

显然,我们会在能让字典序变小的节点中尽量选择靠前的,即左子树比右子树优先。同时,不难证明:

  • 如果当前节点被复制不会使答案更优,则它的右子树一定不会被复制。
  • 在左右子树都能使答案更优的前提下,优先复制左子树。

因此,我们可以执行一个 dfs 框架:

  • 假设当前访问的节点为 �u,复制该节点的代价为 ����cost。
  • 若 �=0u=0 或 ����>�cost>k,返回。
  • 访问当前节点的左儿子 ��lu​,同时将 ����←����+1cost←cost+1。
  • 如果 ��lu​ 需要被复制,则 �u 需要被复制。
  • 否则,在 ��lu​ 不需要被复制的情况下,如果 �u 被复制能让答案更优,则 �u 也需要被复制,且 �←�−����k←k−cost。
  • 如果当前节点需要被复制,访问当前节点的右儿子 ��ru​,并将 ����←1cost←1。

这样,我们就找到了每个节点是否需要被复制。时间复杂度 �(�)O(n)。

标签:cost,int,中序,dfs,复制,CFD2E,节点
From: https://www.cnblogs.com/Lamboofhome/p/17196699.html

相关文章

  • 天梯赛练习题L3-001 凑零钱(dfs 爆搜)
    https://pintia.cn/problem-sets/994805046380707840/exam/problems/994805054207279104题目大意:给定n个硬币,总共需要我们凑出m块钱。问我们能凑出的硬币的最小字典序......
  • AcWing 165. 小猫爬山(dfs)
    https://www.acwing.com/problem/content/167/一共N只小猫,每个缆车最大承重量为W。N只小猫的重量分别是C1、C2……CN。当然,每辆缆车上的小猫的重量之和不能超过W。......
  • 【DFS】LeetCode 剑指 Offer 07. 重建二叉树
    题目链接剑指Offer07.重建二叉树思路递归建树,思路与【DFS】LeetCode105.从前序与中序遍历序列构造二叉树相同。代码classSolution{publicTreeNodebuild......
  • LeetCode 105. 从前序与中序遍历序列构造二叉树
    原题解题目约束题解解法一classSolution{private:unordered_map<int,int>index;public:TreeNode*myBuildTree(constvector<int>&preorder......
  • 二叉树的中序遍历
    1.图的中序遍历classTreeNode{  intval;  TreeNodeleft;  TreeNoderight;  TreeNode(){};  TreeNode(intval){this.val=val;}  Tre......
  • 4868. 数字替换(dfs,剪枝)
    https://www.acwing.com/problem/content/description/4871/似乎没什么好办法,只能暴搜了,bfs对于那么多状态的搜索容易tle(bfs会把所有状态都彻底搜索一遍,相比dfs不方便......
  • DFS
    DFS主要思想:1.终点,2.回溯。一、对于终点,我们要对其做一个特殊的处理也就是对结果的处理,处理完之后结束这一次的递归,即开始这一次递归的回溯二、回溯,有很多人都卡在这里。......
  • 【DFS】LeetCode 46. 全排列
    题目链接46.全排列思路本题是求排列问题.与组合问题不同的是,在排列问题中,不同的数字顺序被视为不同的排列,比如[1,2]与[2,1]是两种不同的排列。搜索树如下图所示,引......
  • 【DFS】LeetCode 90. 子集 II
    题目链接90.子集II思路去重方法与【DFS】LeetCode40.组合总和II思路相似代码classSolution{privateList<List<Integer>>result=newArrayList<>();......
  • DFS 序求 LCA
    很冷门的科技,但是有着显著的使用效果(减少建立虚树的常数)。本文学习自:Alex_Wei的博客首先遍历一遍整棵树,可以得到整棵树的DFS序和每个点的时间戳(记为\(dfn\))。考虑......