区间最值 区间赋值
有 N 个方块排成一排,每个方块都染有颜色,第 i 个的颜色为 Ci,一共有M种颜色,每种颜色的方块都有不同的价值Wi,现在要求找出一段方块,使得其中只出现过一次的方块的价值总和最大。
分析
对于同一种颜色,每次只能取一段。
按顺序遍历,假设取此颜色该区间,将此颜色前一段区间删去,给这一段区间赋值。
然后每一次都取最大值
代码
#include <bits/stdc++.h>
using namespace std; // ____ _ _ __ __
#define ll long long // / ___| | |_| | / /
const ll INF = 0x3f3f3f3f; // | | | _ | V /
const ll N = 1e5 + 5; // | |___ | | | | | |
const ll MOD = 1e9 + 7; // ____| |_| |_| |_|
ll read() {
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1; ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0'; ch = getchar();
}
return x * f;
}
struct segt {
ll *a;
struct Tree {
int l, r;
ll sum, lz;
void update(ll v) {
sum += v;
lz += v;
}
} tree[N * 4];
void modify(ll *arr) {
a = arr;
}
void pushup(int x) {
tree[x].sum = max(tree[2 * x].sum, tree[2 * x + 1].sum);
}
void pushdown(int x) {
if (tree[x].lz != 0) {
tree[2 * x].update(tree[x].lz);
tree[2 * x + 1].update(tree[x].lz);
tree[x].lz = 0;
}
}
void build(int x, int l, int r) {
tree[x].l = l;
tree[x].r = r;
tree[x].lz = 0;
if (l == r) {
tree[x].sum = a[l];
return;
}
int mid = (l + r) / 2;
build(2 * x, l, mid);
build(2 * x + 1, mid + 1, r);
pushup(x); // 如果在建树的过程中给sum赋值,记得后面要pushup
}
void update(int x, int l, int r, ll c) {
int L = tree[x].l, R = tree[x].r;
int mid = (L + R) / 2;
if ((l <= L) && (r >= R)) {
tree[x].update(c);
return;
}
pushdown(x);
if (l <= mid) update(2 * x, l, r, c);
if (r > mid) update(2 * x + 1, l, r, c);
pushup(x);
}
ll query(int x, int l, int r) {
int L = tree[x].l, R = tree[x].r;
ll mid = (L + R) / 2;
ll res = 0;
if ((l <= L) && (r >= R)) { // 要更新区间包括了该区间
return tree[x].sum;
}
pushdown(x);
if (l <= mid) res = max(res, query(2 * x, l, r));
if (r > mid) res = max(res, query(2 * x + 1, l, r));
pushup(x);
return res;
}
} tree;
int n, m;
ll c[N], w[N];
vector<int> v[N];
ll ans;
ll a[N];
int main() {
while (cin >> n >> m) {
ans = 0;
tree.modify(a);
tree.build(1, 1, n);
for (int i = 1; i <= n; i++) c[i] = read(), v[i].clear();
for (int i = 1; i <= m; i++) w[i] = read();
for (int i = 1; i <= n; i++) {
if (v[c[i]].size() == 0) {
tree.update(1, 1, i, w[c[i]]);
}
else if (v[c[i]].size() == 1) {
tree.update(1, 1, v[c[i]][0], -w[c[i]]);
tree.update(1, v[c[i]][0] + 1, i, w[c[i]]);
}
else {
tree.update(1,
v[c[i]][v[c[i]].size() - 2] + 1,
v[c[i]][v[c[i]].size() - 1] + 1,
-w[c[i]]);
tree.update(1,
v[c[i]][v[c[i]].size() - 1] + 1,
i,
w[c[i]]);
}
v[c[i]].push_back(i);
ans = max(ans, tree.query(1, 1, n));
}
cout << ans << endl;
}
return 0;
} 
京公网安备 11010502036488号