HDU 5489 Removed Interval (合肥网络赛 1006 )

题目链接

题意, 给一串字符串, 问删掉一段 L 长度的子串之后, 剩下的串的 LIS 最大长度。

做法,首先先用 O(n log n) 的方法二分求出原串的 LIS, 然后用 dp 求出一段子串中间去掉 L 长度后的 LIS。

用 LIS { Str } 表示串 Str 的 LIS, S [ l, r ]  表示子串 S(l ~ r)

则转移方程可以表示为: dp[i] = max( LIS { S [ 0, i - L  ] + S [ i, i ] } ,  dp [ pos ] + LIS { S [ pos , i ] } )     (L < pos  <= i )

其中 dp 部分也可以沿用求 LIS 的二分思想求出 。


参考代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 100005;

int a[N], b[N], f[N], c[N], d[N], g[N], CASE;

int main() {
  int T;
  scanf("%d", &T);
  while (T--) {
    int n, L;
    scanf("%d %d", &n, &L);
    for (int i = 1; i <= n; i++) scanf("%d", a + i);
    a[++n] = 1e9 + 10;
    int k = 0, h = 0, w = 0;
    memset(b, 0x3f, sizeof b);
    memset(c, 0x3f, sizeof c);
    memset(d, 0x3f, sizeof d);
    b[0] = c[0] = d[0] = - 1e9 - 10;
    for (int i = 1; i <= n; i++) {
      f[i] = lower_bound(b, b + k + 2, a[i]) - b;
      b[f[i]] = min(b[f[i]], a[i]);
      if (f[i] > k) k = f[i];
      if (i <= L) continue;
      int x = lower_bound(d, d + w + 2, a[i]) - d;
      int y = lower_bound(c, c + h + 2, a[i]) - c;
      g[i] = max(x, y);
      d[g[i]] = min(d[g[i]], a[i]);
      if (g[i] > w) w = g[i];
      int p = f[i - L];
      c[p] = min(c[p], a[i - L]);
      d[p] = min(c[p], d[p]);
      if (p > h) h = p;
    }
    printf("Case #%d: %d\n", ++CASE, w - 1);
  }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值