AcWing 4550. 超级跳跳跳

题目简化后就是 LIS 将原本的价值改成了 ai,我们设 fi 表示对于前 i 个数,必定选 i,那么 fi=maxai>ak{fk+ai}

// #define FILE_INPUT
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define rep(i, a, b) for (int i = a, END##i = b; i <= END##i; i++)
#define per(i, a, b) for (int i = a, END##i = b; i >= END##i; i--)

void Init();
void Solve();

signed main() {
    cin.sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    #ifdef FILE_INPUT
        freopen("input.in", "r", stdin);
    #endif

    int T = 1;
    // cin >> T;
    while (T--) {
        Init();
        Solve();
    }
    return 0;
}

using LL = long long;
using ULL = unsigned long long;

const int Mod = 1e9 + 7;
const int Inf = 0x3f3f3f3f;
const LL InfLL = 0x3f3f3f3f3f3f3f3f;

const int N = 1010;
int n, f[N], a[N];

void Init() {
}

void Solve() {
    while (cin >> n, n) {
        rep(i, 1, n) cin >> a[i];
        int ans = 0;
        rep(i, 1, n) {
            f[i] = a[i];
            rep(j, 1, i - 1) if (a[i] > a[j]) {
                f[i] = max(f[i], f[j] + a[i]);
            }
            ans = max(ans, f[i]);
        }
        cout << ans << "\n";
    }
}

上面的代码时间复杂度是 O(n2) 的,对于 n=105 时明显过不去,我们可以利用线段树来进行优化,从而将时间复杂度变为 O(nlog2n),当然,线段树也可以优化 LIS 问题(虽然没必要,用二分就行)。

将这一行优化成 log2n

rep(j, 1, i - 1) if (a[i] > a[j]) {
	f[i] = max(f[i], f[j] + a[i]);
}

代码:

// #define FILE_INPUT
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define rep(i, a, b) for (int i = a, END##i = b; i <= END##i; i++)
#define per(i, a, b) for (int i = a, END##i = b; i >= END##i; i--)

void Init();
void Solve();

signed main() {
    cin.sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    #ifdef FILE_INPUT
        freopen("input.in", "r", stdin);
    #endif

    int T = 1;
    // cin >> T;
    while (T--) {
        Init();
        Solve();
    }
    return 0;
}

using LL = long long;
using ULL = unsigned long long;

const int Mod = 1e9 + 7;
const int Inf = 0x3f3f3f3f;
const LL InfLL = 0x3f3f3f3f3f3f3f3f;

const int N = 1010;
int n, f[N], a[N], rk[N], tot;

#define lc (p << 1)
#define rc (p << 1 | 1)
int tree[N << 2], tag[N << 2];
void pushdown(int p) {
    if (tag[p] != -1) {
        tree[lc] = max(tree[lc], tag[p]);
        tag[lc] = max(tag[lc], tag[p]);
        tree[rc] = max(tree[rc], tag[p]);
        tag[rc] = max(tag[rc], tag[p]);
        tag[p] = -1;
    }
}
void pushup(int p) {
    tree[p] = max(tree[lc], tree[rc]);
}
void update(int p, int L, int R, int l, int r, int d) {
    if (l <= L && R <= r) {
        tree[p] = max(tree[p], d);
        tag[p] = max(tag[p], d);
        return;
    }
    pushdown(p);
    int Mid = L + R >> 1;
    if (l <= Mid) update(lc, L, Mid, l, r, d);
    if (r > Mid) update(rc, Mid + 1, R, l, r, d);
    pushup(p);
}
int query(int p, int L, int R, int x) {
    if (L == x && R == x) return tree[p];
    pushdown(p);
    int Mid = L + R >> 1;
    if (x <= Mid) return query(lc, L, Mid, x);
    return query(rc, Mid + 1, R, x);
}

void Init() {
}

void Solve() {
    while (cin >> n, n) {
        tot = 0;
        memset(tree, 0, sizeof(tree));
        memset(tag, -1, sizeof(tag));
        rep(i, 1, n) {
            cin >> a[i];
            rk[++tot] = a[i];
        }
        sort(rk + 1, rk + tot + 1);
        tot = unique(rk + 1, rk + tot + 1) - rk - 1;
        int ans = 0;
        rep(i, 1, n) {
            int x = lower_bound(rk + 1, rk + tot + 1, a[i]) - rk;
            f[i] = query(1, 1, tot, x) + a[i];
            if (x + 1 <= tot) update(1, 1, tot, x + 1, tot, f[i]);
            ans = max(ans, f[i]);
        }
        cout << ans << "\n";
    }
}

我是不会告诉你我是为了凸显时间快才用离散化的 😃

posted @   wh2011  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示