[POI2015]KIN[线段树]

很套路的维护最大和子段

#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
", 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
", ans);
	return 0;	
}
原文地址:https://www.cnblogs.com/hjmmm/p/10689044.html