n個位置,每個位置有兩個屬性s,c,要求選擇3個位置i,j,k,使得si<sj<sk,並使得ci+cj+ck 最小
輸入格式:
一行一個整數,n,3<=n<=3000
一行n個整數,即s
再一行n個整數,即c
動態規劃 + 權值線段樹優化。時間複雜度 O(nlog(n))
#include <bits/stdc++.h>
using namespace std;
const int inf = 1e9;
const int maxn = 1e6 + 5;
struct Tree {
int l, r, mm;
}tree[maxn];
int L[maxn], R[maxn], s[maxn], c[maxn];
int Hash[maxn], len;
void pushup(int i) {
tree[i].mm = min(tree[i * 2].mm, tree[i * 2 + 1].mm);
}
void build(int i, int l, int r) {
tree[i].l = l;
tree[i].r = r;
tree[i].mm = inf;
if (l >= r) return ;
int mid = (l + r) / 2;
build(i * 2, l, mid);
build(i * 2 + 1, mid + 1, r);
pushup(i);
}
void updata(int i, int p, int v) {
if (tree[i].l == tree[i].r) {
tree[i].mm = min(tree[i].mm, v);
return ;
}
int mid = (tree[i].l + tree[i].r) / 2;
if (mid >= p) {
updata(i * 2, p, v);
} else {
updata(i * 2 + 1, p, v);
}
pushup(i);
}
int query(int i, int l, int r) {
if (l > r) return inf;
if (tree[i].l == l && tree[i].r == r) {
return tree[i].mm;
}
int mid = (tree[i].l + tree[i].r) / 2;
if (mid >= r) {
return query(i * 2, l, r);
} else if (l > mid) {
return query(i * 2 + 1, l, r);
} else {
return min(query(i * 2, l, mid), query(i * 2 + 1, mid + 1, r));
}
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> s[i];
Hash[++len] = s[i];
}
for (int i = 1; i <= n; i++) {
cin >> c[i];
}
sort (Hash + 1, Hash + len + 1);
len = unique(Hash + 1, Hash + len + 1) - Hash - 1;
for (int i = 1; i <= n; i++) {
s[i] = lower_bound(Hash + 1, Hash + len + 1, s[i]) - Hash;
}
build(1, 1, len);
for (int i = 1; i <= n; i++) {
L[i] = query(1, 1, s[i] - 1);
updata(1, s[i], c[i]);
}
build(1, 1, len);
for (int i = n; i >= 1; i--) {
R[i] = query(1, s[i] + 1, len);
updata(1, s[i], c[i]);
}
int ans = inf;
for (int i = 1; i <= n; i++) {
ans = min(ans, L[i] + R[i] + c[i]);
}
if (ans != inf) {
cout << ans << endl;
} else {
cout << "-1" << endl;
}
return 0;
}