HDU 5489 Removed Interval (LIS变形)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5489

给你n个数,要删去其中连续的L个,问你删去之后的LIS最大是多少?

我们先预处理出以i下标为开头的LIS,存到数组中。

然后可以枚举长为L的区间,每次移动,左边增加一个,右边删除一个。

最长上升子序列长度 = 窗口右边以右边第一个元素开头的最长上升子序列 + 窗口左边最大元素小于窗口右边第一个元素的最长上升子序列。

比如 1 2 [4 3] 2 3 5  ,  LIS = 3 + 1 = 4

求以i开头的LIS 只要倒着求最长下降子序列 or 倒着a[i]变负求最长上升子序列即可。

代码写的有点乱。

 1 //#pragma comment(linker, "/STACK:102400000, 102400000")
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <ctime>
10 #include <list>
11 #include <set>
12 #include <map>
13 using namespace std;
14 typedef long long LL;
15 typedef pair <int, int> P;
16 const int N = 1e5 + 5;
17 int dp1[N], dp2[N], a[N], inf = 1e9 + 7;
18 int y[N], x[N]; // y[i]表示以i下标为开头的LIS,x[i]表示以i为结尾的LIS
19
20 int main()
21 {
22     int t, n, m;
23     scanf("%d", &t);
24     for(int ca = 1; ca <= t; ++ca) {
25         scanf("%d %d", &n, &m);
26         for(int i = 1; i <= n; ++i) {
27             scanf("%d", a + i);
28             dp1[i] = dp2[i] = inf;
29         }
30         dp2[0] = dp1[0] = inf;
31         int ans = 0;
32         for(int i = n; i >= 1; --i) { //倒着求变负,求以i开头的LIS
33             int pos = lower_bound(dp2, dp2 + n, -a[i]) - dp2;
34             y[i] = pos + 1;
35             //cout << y[i] << endl;
36             dp2[pos] = -a[i];
37             if(i == m + 1) {
38                 ans = lower_bound(dp2, dp2 + n, inf) - dp2;
39             }
40         }
41         //cout << ans << endl;
42         for(int i = 1; i <= n; ++i) {
43             int pos = lower_bound(dp1, dp1 + n, a[i]) - dp1;
44             x[i] = pos + 1;
45             dp1[pos] = a[i];
46             if(i == n - m) {
47                 ans = max(int(lower_bound(dp1, dp1 + n, inf) - dp1), ans);
48                 break;
49             }
50         }
51         //cout << ans << endl;
52         printf("Case #%d: ", ca);
53         dp1[0] = inf;
54         for(int i = 1; i <= n; ++i) {
55             dp1[i] = inf;
56         }
57         for(int i = m + 1; i <= n; ++i) {
58             int pos = lower_bound(dp1, dp1 + n, a[i] - 1) - dp1; //求滑窗左边刚好小于滑窗右边第一个数的LIS
59             ans = max(ans, y[i] + (a[i] - 1 == a[pos] ? pos + 1 : pos));
60             *lower_bound(dp1, dp1 + n, a[i - m]) = a[i - m];
61         }
62         printf("%d\n", ans);
63     }
64     return 0;
65 }
时间: 2024-08-27 15:26:12

HDU 5489 Removed Interval (LIS变形)的相关文章

HDU 5489 Removed Interval (LIS,变形)

题意: 给出一个n个元素的序列,要求从中删除任一段长度为L的连续子序列,问删除后的LIS是多少?(n<=10w, L<=n ,元素可能为负) 思路: 如果会O(nlogn)求普通LIS的算法,这道题将变得很简单. 首先按照求LIS的思路,当扫到元素a[i]并完成操作后,a[1->i]就是一段已经处理完成的序列,假设a[i+1]->a[i+L]这一段是将要删去的,那么将分成两段:a[0]->a[i]和a[i+L+1]->a[n]. 假设后一段以a[i+L+1]开头,而前段

【二分】【最长上升子序列】HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5489 题目大意: 一个N(N<=100000)个数的序列,要从中去掉相邻的L个数(去掉整个区间),使得剩余的数最长上升子序列(LIS)最长. 题目思路: [二分][最长上升子序列] 首先,假设去掉[i,i+m-1]这L个数,剩余的LIS长度为max(i左端最后一个不大于a[i+m]的LIS长度+a[i+m]开始到最后的LIS长度). 所以,我们从n到1逆向先求最长下降子序列的长度f[i],就可以知

HDU 5489 Removed Interval

题意:求一段序列中删掉L个连续元素后的LIS. 解法:我的想法很复杂= =怎么说呢……首先用nlogn的方法求LIS得到的序列dp的第i项的意义为上升子序列所有长度为i的序列结尾元素的最小值,那么先倒着用nlogn的方法求一遍最长下降子序列记为dp1,记录每一步怎么更新的dp1,再正着求一遍最长上升子序列,每次看a[i]的时候二分的在i+k到结尾的dp1中找第一个比a[i]大的数设为dp1[pos],所以当前枚举的答案即为以a[i]作为结尾的最长上升子序列+后一段以dp1[pos]开头的最长上升

HDU 5489 Removed Interval 2015 ACM/ICPC Asia Regional Hefei Online

定义f[i]表示以i为开头往后的最长上升子序列,d[i]表示以i为结尾的最长上升子序列. 先nlogn算出f[i], 从i-L开始枚举f[i],表示假设i在LIS中得到的最长上升子序列,往[0,i-L)里找到满足ai>aj中dj值最大的.用dj+f[i]更新. 但是这样会少考虑一种情况,即i-L以后都不在最终的答案里面,这样一定是以[0~i-L)中的某个结尾的,所以还要用d[j]去更新答案. #include<bits/stdc++.h> using namespace std; con

hdu 5256 序列变换 (LIS变形)

序列变换 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 519    Accepted Submission(s): 245 Problem Description 我们有一个数列A1,A2...An,你现在要求修改数量最少的元素,使得这个数列严格递增.其中无论是修改前还是修改后,每个元素都必须是整数. 请输出最少需要修改多少个元素.

Hdu 5489 合肥网络赛 1009 Removed Interval

跳跃式LIS(nlogn),在普通的转移基础上增加一种可以跨越一段距离的转移,用一颗新的树状数组维护,同时,我们还要维护跨越完一次后面的转移,所以我用了3颗树状数组.. 比赛的时候一句话位置写错了,然后就...雪崩 呆马: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <vector> 6 #include

hdu 1087(LIS变形)

Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 31458    Accepted Submission(s): 14128 Problem Description Nowadays, a kind of chess game called “Super Jumping!

HDU 4352 XHXJ&#39;s LIS

XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1423    Accepted Submission(s): 544 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then careful

HDU5489 LIS变形

Removed Interval Problem Description Given a sequence of numbers A=a1,a2,…,aN , a subsequence b1,b2,…,bk of A is referred as increasing if b1<b2<…<bk . LY has just learned how to find the longest increasing subsequence (LIS).Now that he has to se