1. 程式人生 > >[POI2015]KIN[線段樹]

[POI2015]KIN[線段樹]

mdf cst string int ons pac 線段 scanf lse

很套路的維護最大和子段

#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;   
}

[POI2015]KIN[線段樹]