社区讨论

基础赛T3 O(n²k)级别的算法过了??

灌水区参与者 9已保存回复 13

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
13 条
当前快照
1 份
快照标识符
@lo17xlpg
此快照首次捕获于
2023/10/22 16:40
2 年前
此快照最后确认于
2023/11/02 16:30
2 年前
查看原帖
CPP
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int n, k, t;
ll dp[510][510];
int l[510], r[510], val[510]; // 存储一个区间,l[i]代表i出现的最小下标,val代表i的价值
int a[510], b[510];
ll res;
int main(){
    cin >> n >> k;
    for (int i=1; i<=n; i++) { scanf("%d", &a[i]); }
    for (int i=1; i<=n; i++) { scanf("%d", &b[i]); }
    for (int i=1; i<=n; i++) { // 初始化区间数组
        t = a[i];
        if (!l[t]) {
            l[t] = i, r[t] = i, val[t] = b[a[i]];
        }
        else{
            r[t] = i;
        }
    }
    // 处理dp数组。dp[i][j]代表已选用了i种颜色,且最右边一个选用的颜色为j时的价值
    for (int i=1; i<=n; i++) { dp[1][i] = val[i]; } // 边界处理
    // 核心代码 (写到这里才发现O(n^3)...)
    for (int i=2; i<=k; i++){
        for (int j=1; j<=n; j++){
            for (int x=1; x<=l[j]; x++){
                if (dp[i-1][a[x]] && x == r[a[x]] && a[x] < j){ // a[x]是一个区间的右边界,并且拼接后满足单调递增
                    dp[i][j] = max(dp[i][j], dp[i-1][a[x]] + val[j]);
                }
            }
        }
    }
    for (int i=1; i<=n; i++) { res = max(res, dp[k][i]); }
    if (res) { cout << res; }
    else { cout << -1; }
    return 0;
}
乱写的屎山,时间复杂度瓶颈应该在三重循环那里,是O(n²k),在n == k == 500,a中无重复元素的时候就是500^3 > 1e8,应该会TLE。 本来只想骗部分分,结果交上去不但AC了,甚至用时最长的点只有28ms???不知道是不是最内层循环的时间复杂度估计错了,求dalao解惑

回复

13 条回复,欢迎继续交流。

正在加载回复...