[POI2015]KIN[线段树]

时间:2021-07-16 01:36:18

很套路的维护最大和子段

#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <complex>
#include <ctime>
#include <vector>
#define mp(x, y) make_pair(x, y)
using namespace std;
const int N = 1e6 + 5;
int n, m, L;
long long ans, res;
int a[N], b[N];
int pre[N], rec[N];
bool vis[N]; struct Seg{
long long w[N << 2], ls[N << 2], rs[N << 2], sum[N << 2];
void update(int rt){
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
w[rt] = rs[rt << 1] + ls[rt << 1 | 1];
ls[rt] = max(ls[rt << 1], sum[rt << 1] + ls[rt << 1 | 1]);
rs[rt] = max(rs[rt << 1 | 1], sum[rt << 1 | 1] + rs[rt << 1]);
// printf("%d %lld %lld %lld\n", rt, w[rt], ls[rt], rs[rt]);
}
void mdf(int rt, int l, int r, int x, int d){
if(l == r){sum[rt] = d, ls[rt] = rs[rt] = w[rt] = max(0, d); return;}
int mid = l + ((r - l) >> 1);
if(x <= mid) mdf(rt << 1, l, mid, x, d);
else mdf(rt << 1 | 1, mid + 1, r, x, d);
update(rt);
}
}seg; int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]), pre[i] = rec[a[i]], rec[a[i]] = i;
for(int i = 1; i <= m; ++i) scanf("%d", &b[i]);
for(int i = 1; i <= n; ++i){
seg.mdf(1, 1, n, i, b[a[i]]);
if(pre[i]) seg.mdf(1, 1, n, pre[i], -b[a[i]]);
if(pre[pre[i]]) seg.mdf(1, 1, n, pre[pre[i]], 0);
ans = max(ans, seg.w[1]);
}
printf("%lld\n", ans);
return 0;
}