• 某题目1 二叉搜索树 最长不下降子序列


    Description

    给你一棵二叉树,每个点有点权(整数),你可以改变某些点的点权(只能改成整数),使这棵树满足二叉搜索树的性质,求满足条件最少的修改的点的数目。

    n <= 1e5

    Solution

    一看到二叉搜索树,就要做中序遍历,得到序列a

    要使修改的点的数量最少,即保留的最多原来的点。

    如果能把点权改成小数的话,这个就可以直接做最长上升子序列。

    但现在点权只能改成整数,需要考虑空隙的问题。

    我们不妨设bi = ai-i,可以发现问题就转化为最长不下降子序列。

    为什么呢?

    设aj和ai,且满足i > j,若i和j都保留,则必须满足ai-aj >= i-j,整理得ai-i >= aj-j

    最长的可保留子序列即ai-i的最长不下降子序列。

    Code

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <string>
     5 #include <algorithm>
     6 #include <stack>
     7 
     8 using namespace std;
     9 
    10 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_;  ++i)
    11 #define mset(a, b) memset(a, b, sizeof(a))
    12 const int maxn = 1e5+10;
    13 int n, a[maxn], b[maxn], b_cnt;
    14 int t[maxn], t_cnt;
    15 int ls[maxn], rs[maxn];
    16 int mx[maxn*4];
    17 
    18 void build_tree(int rt, int l, int r)
    19 {
    20     mx[rt] = 0;
    21     if (l == r) return ;
    22     int mid = (l+r)>>1;
    23     build_tree(rt<<1, l, mid);
    24     build_tree((rt<<1)+1, mid+1, r);
    25 }
    26 
    27 void pushup(int rt) { mx[rt] = max(mx[rt<<1], mx[(rt<<1)+1]); }
    28 
    29 void modify(int rt, int l, int r, int p, int d)
    30 {
    31     if (l == r) { mx[rt] = max(mx[rt], d); return ; }
    32     int mid = (l+r)>>1;
    33     if (p <= mid) modify(rt<<1, l, mid, p, d);
    34     else modify((rt<<1)+1, mid+1, r, p, d);
    35     pushup(rt);
    36 }
    37 
    38 int query(int rt, int l, int r, int L, int R)
    39 {
    40     if (L <= l && r <= R) return mx[rt];
    41     int mid = (l+r)>>1, ret = 0;
    42     if (L <= mid) ret = query(rt<<1, l, mid, L, R);
    43     if (R > mid) ret = max(ret, query((rt<<1)+1, mid+1, r, L, R));
    44     return ret;
    45 }
    46 
    47 int f[maxn];
    48 stack <int> s;
    49 bool vis[maxn];
    50 
    51 void bfs(int k)
    52 {
    53     s.push(k);
    54     mset(vis, 0);
    55     while (!s.empty())
    56     {
    57         int u = s.top(); 
    58         if (ls[u] != -1 && !vis[ls[u]]) { s.push(ls[u]); continue ; }
    59         vis[u] = true, b[++b_cnt] = a[u], b[b_cnt] -= b_cnt; s.pop();
    60         if (rs[u] != -1 && !vis[rs[u]]) { s.push(rs[u]); continue ; }
    61     }
    62 }
    63 
    64 int main()
    65 {
    66     scanf("%d", &n);
    67     t_cnt = 0;
    68     REP(i, 1, n) scanf("%d", &a[i]);
    69     mset(ls, -1), mset(rs, -1);
    70     REP(i, 2, n)
    71     {
    72         int fa, ty;
    73         scanf("%d %d", &fa, &ty);
    74         (ty ? rs[fa] : ls[fa]) = i;
    75     }
    76     b_cnt = 0, bfs(1);
    77     REP(i, 1, n) t[i] = b[i];
    78     sort(t+1, t+n+1);
    79     t_cnt = 1;
    80     REP(i, 2, n)
    81         if (t[i] != t[i-1]) t[++t_cnt] = t[i];
    82     REP(i, 1, n)
    83         b[i] = lower_bound(t+1, t+t_cnt+1, b[i])-t;
    84     build_tree(1, 1, t_cnt);
    85     REP(i, 1, n)
    86     {
    87         f[i] = query(1, 1, t_cnt, 1, b[i])+1;
    88         modify(1, 1, t_cnt, b[i], f[i]);
    89     }
    90     printf("%d
    ", n-mx[1]);
    91     return 0;
    92 }
    View Code
  • 相关阅读:
    SpringBoot整合RabbitMQ
    RabbitMQ消息确认机制
    RabbitMQ六种队列模式-简单队列模式
    RabbitMQ六种队列模式-工作队列模式
    RabbitMQ六种队列模式-发布订阅模式
    RabbitMQ六种队列模式-路由模式
    RabbitMQ六种队列模式-主题模式
    RabbitMQ简单介绍+Windows环境安装
    SpringBoot整合ActiveMQ发送邮件
    下载缓慢文件记录,持续更新[2019-10-29]
  • 原文地址:https://www.cnblogs.com/-ZZB-/p/6635641.html
Copyright © 2020-2023  润新知