Protocol

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
考虑以 1 为根时,路径两个端点的 LCA 是谁。对于每个点,计算出它到子树内点期望距离的最大值 a[i]和子树内点到它期望距离的最大值 b[i]。假设 LCA 是 i,枚举起点在以 i 的哪一个孩子为根 的 子 树 内 , 设 是 j , 那 么 路 径 长 度 的 最 大 值 就 是b[j]+f[<j,i>]+max{a[k]+f[<i,k>]}(k 是 i 的孩子且 j≠k)。求出 a[k]+f[<i,k>]最大和次大的子树即可在 O(d[i])的时间内计算出两个以 i 为 LCA 的端点的期望距离的最大值,对所有这些最大值再求一个最大值即可

#include <bits/stdc++.h>
using namespace std;
#define P(a) putchar(a+48)
#define ll long long
#define pL pair<ll,ll>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define writen(x) write(x),puts("")
#define writep(x) write(x),putchar(' ')
const ll mod = 998244353;
const ll maxn = 1e6 + 5;
const ll inf = 1e18 ;
inline void read(ll &a)
{
 a = 0;
 ll  f = 1;
 char ch = getchar();
 while(ch < '0' || ch > '9')
 {
  if(ch == '-') f = -1;
  ch = getchar();
 }
 while(ch <= '9' && ch >= '0')
 {
  a = (a << 3) + (a << 1) + ch - '0';
  ch = getchar();
 }
 a *= f;
}
inline void write(ll s)
{
 if (s < 0) P(-3),s = -s;
 if (s > 9) write(s / 10);
 P(s % 10);
}
ll n,k;
ll a[maxn],b[maxn],f[2][maxn];
int main()
{
 read(n);
 read(k);
 for(int i = 1;i <= n;i++) read(a[i]);
 for(int i = 1;i <= n;i++) b[i] = a[n - i + 1];
 for(int i = 1;i <= n;i++)
 {
  for(int j = max(1LL,i - k);j <= min(n,i + k);j++)
  {
   ll x = i&1;
   if(a[i] == b[j])
    f[x][j] = max(max(f[x^1][j],f[x][j-1]),f[x^1][j-1]+1);
   else
    f[x][j]=max(max(f[x^1][j],f[x][j-1]),f[x^1][j-1]);
  }
 }
 if(n - f[n&1][n] > k)
  puts("fake");
 else
  cout<<n - f[n&1][n];
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值