CSU 1551 Longest Increasing Subsequence Again(树状数组 或者 LIS变形)

题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1551

升级版:Uva 1471

题意:

  让你求删除一段连续的子序列之后的LIS。

题解:  

  预处理:先求一个last[i],以a[i]为开始的合法最长上升子序列的长度。再求一个pre[i],以a[i]为结尾的合法最长上升子序列长度。

  答案应该为 

  max(以j结束的合法最长上升子序列长度) + 以a[i]为开始的合法最长上升子序列长度。 其中j<a[i]。

  1)通过树状数组维护区间最值。

  2)通过LIS 维护。(详细请看http://www.cnblogs.com/denghaiquan/p/6761600.html

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define ms(a, b)  memset((a), (b), sizeof(a))
16 //#define LOCAL
17 #define eps 0.0000001
18 typedef long long LL;
19 const int inf = 0x3f3f3f3f;
20 const int maxn = 10000+10;
21 const int mod = 1000000007;
22 int a[maxn], pre[maxn], last[maxn], c[maxn];
23 int n;
24 int lowbit(int x){
25     return x&(-x);
26 }
27 int ask(int x)
28 {
29     int ans = 0;
30     while(x>0){
31         ans = max(ans, c[x]);
32         x-=lowbit(x);
33     }
34     return ans;
35 }
36 void updata(int x, int d)
37 {
38     while(x <= 1e4){
39         c[x] = max (c[x] , d);
40         x += lowbit(x);
41     }
42 }
43 void solve()
44 {
45     int ans = 0;
46     ms(c, 0);
47     for(int i=1;i<=n;i++)    scanf("%d", &a[i]);
48     //last[i] 是第i个开始和合法后缀
49     last[n] = 1;
50     for(int i = n-1; i>0;i--){
51         if(a[i] < a[i+1]){
52             last[i] = last[i+1] + 1;
53         }else   last[i] = 1;
54     }
55     //pre[i] 是第i个结束的合法前缀
56     pre[1] = 1;
57     for(int i=2;i<=n;i++){
58         if(a[i] > a[i-1]){
59             pre[i] = pre[i-1] + 1;
60         }else   pre[i] = 1;
61     }
62     for(int i=1;i<=n;i++){
63         ans = max(ans, last[i] + ask(a[i]-1));
64         updata(a[i], pre[i]);
65     }
66     printf("%d
", ans);
67 }
68 int main()
69 {
70     #ifdef LOCAL
71         freopen("jumping.in", "r", stdin);
72 //      freopen("output.txt", "w", stdout);
73     #endif // LOCAL
74     while(~scanf("%d", &n)){
75         solve();
76     }
77     return 0;
78 }
View Code

升级版,应该数的范围在1e9所以无法用树状数组维护。只能用LIS或者set来维护。

原文地址:https://www.cnblogs.com/denghaiquan/p/6761710.html