首页 > 其他分享 >AcWing 1017. 怪盗基德的滑翔翼——最长上升子序列

AcWing 1017. 怪盗基德的滑翔翼——最长上升子序列

时间:2023-11-18 10:12:50浏览次数:420  
标签:int res 滑翔翼 怪盗 cin -- max 基德 dp

最长上升子序列


1、\(O(n^{2})\) 简单DP做法

\[dp[i]=\max_{h[j] < h[i]} [dp[j] + 1] \]

#include<bits/stdc++.h>
using namespace std;

const int N = 105;

int h[N];
int dp[N];

int main() {
    int T; cin >> T;
    while(T --) {
        int n; cin >> n;
        for(int i = 1; i <= n; ++ i) cin >> h[i];
        memset(dp, 0, sizeof(dp));
        int res = 0;
        for(int i = 1; i <= n; ++ i) {
            for(int j = 1; j < i; ++ j) {
                if(h[i] > h[j]) dp[i] = max(dp[i], dp[j] + 1);
            }
            res = max(res, dp[i]);
        }
        memset(dp, 0 ,sizeof(dp));
        for(int i = 1; i <= n; ++ i) {
            for(int j = 1; j < i; ++ j) {
                if(h[i] < h[j]) dp[i] = max(dp[i], dp[j] + 1);
            }
            res = max(res, dp[i]);
        }
        cout << res + 1 << endl;
    }
    return 0;
}

2、\(O(nlogn)\)的二分+贪心法

简单来说:就是q[i]表示所有序列为i的上升序列的最小末尾元素, 如[1,2,3],[5,4,2]这种长度为3的序列,那么q[3]=2。这样处理到第i位数字前,q数组就维护了[1~i-1]所有序列的最小最后一个元素,那么想想看能把h[i]加在哪个位置,那么dp[i]=该位置编号。 至于这个位置就是第一个大于等于h[i]的位置。

#include<bits/stdc++.h>
using namespace std;

const int N = 105;

int h[N];
int q[N];

int main() {
    int T; cin >> T;
    while(T --) {
        int n; cin >> n;
        for(int i = 1; i <= n; ++ i) cin >> h[i];
        memset(q, 0x3f3f3f3f, sizeof(q));
        int res = 0;
        for(int i = 1; i <= n; ++ i) {
            int x = h[i];
            int tx = lower_bound(q + 1, q + n + 1, x) - q;
            q[tx] = x;
            res = max(res, tx);
        }
        memset(q, 0x3f3f3f3f, sizeof(q));
        for(int i = n; i >= 1; --i) {
            int x = h[i];
            int tx = lower_bound(q + 1, q + n + 1, x) - q;
            q[tx] = x;
            res = max(res, tx);
        }
        
        cout << res << endl;
    }
    return 0;
}

3、\(O(nlogn)\) 树状数组优化

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;

int h[N];
int q[N];
int c[N];

// 树状数组维护区间最大值模板
int lowbit(int x){ return x & -x;}

int ask(int x) {
	int ans = 0;
	for(; x; x -= lowbit(x)) ans = max(ans, c[x]);
	return ans;
}

void add(int x, int y) {
	for(; x < N; x += lowbit(x)) c[x] = max(c[x], y);
}


int main() {
    int T; cin >> T;
    while(T --) {
        int n; cin >> n;
        for(int i = 1; i <= n; ++ i) cin >> h[i];
        int res = 0;
        memset(c, 0, sizeof(c));
        for(int i = 1; i <= n; ++ i) {
            add(h[i], ask(h[i] - 1) + 1);
        }
        res = max(res, ask(N - 1));
        memset(c, 0, sizeof(c));
        for(int i = n; i >= 1; -- i) {
            add(h[i], ask(h[i] - 1) + 1);
        }
        res = max(res, ask(N - 1));
        cout << res << endl;
    }
    return 0;
}

标签:int,res,滑翔翼,怪盗,cin,--,max,基德,dp
From: https://www.cnblogs.com/A-sc/p/17840101.html

相关文章

  • 怪盗基德的滑翔翼
    怪盗基德的滑翔翼题目概述:怪盗基德可以选择一个方向,并沿着该方向进行滑行,规定他只能从较高的楼房移动到较低的楼房,问他最多可以走过多少栋楼房。解题思路:很容易将该题抽象为最长上升子序列模型,需要注意的是本题可以选择滑行的方向,也就是正反方向分别进行dp,取最大值#include<io......
  • 怪盗基德的滑翔翼C++
    题目描述】怪盗基德是一个充满传奇色彩的怪盗,专门以珠宝为目标的超级盗窃犯。而他最为突出的地方,就是他每次都能逃脱中村警部的重重围堵,而这也很大程度上是多亏了他随身携带的便于操作的滑翔翼。有一天,怪盗基德像往常一样偷走了一颗珍贵的钻石,不料却被柯南小朋友识破了伪装,而他的......
  • 怪盗基德的滑翔翼
    正着求一遍最长上升子序列问题,再反着求一遍最长上升子序列问题#include<bits/stdc++.h>usingnamespacestd;constintN=210;intn;inta[N];intf[N];intmain......
  • HDU-4552-怪盗基德的挑战书
    怪盗基德的挑战书TimeLimit:3000/1000ms(Java/Other)MemoryLimit:65535/32768K(Java/Other)TotalSubmission(s):26AcceptedSubmission(s):10Font:Time......
  • dp 2 怪盗基德的滑翔翼
    题目链接:http://noi.openjudge.cn/ch0206/4977/最长上升子序列的模型往左边跳,就是最长上升子序列;往右边跳是最长下降子序列,只要reverse一下,就可以转换成最长上升子序......