2017年8月15日提高组T3 电影

来源:互联网 发布:万户网络怎么样 编辑:程序博客网 时间:2024/04/29 05:50

Description


给有m部电影,每一部都有一个好看值w。
在n天里面,每一天都会放一部电影,其中第i天放的是第f[i]部电影,
现在,你可以任意选择一个区间[l,r],然后观看第l天到第r天内所有的电影。但是,如果同一部电影你观看了多于一次,你就无法获得这部电影的好看值。问最大好看值总和。

Input


第一行两个整数n,m,表示点数和操作数。
第二行包含n个整数,表示f[1],f[2]…f[n]。
第三行包含m个整数,表示w[1],w[2]…w[n]。

Output


输出最大好看值总和。

Hint


对于30%的数据,n,m<=1000.
对于100%的数据,n,m<=100000,1<=f[i]<=m,1<=w[i]<=1000000

Source


BY BPM

Solution


对于每个电影记录下一次出现的位置,枚举l的位置并线段树动态修改。第一次出现的我们计为+w,第二次的-w,第三次的移动一下即可

Code


#include <stdio.h>#include <string.h>#include <math.h>#include <queue>#include <vector>#include <algorithm>#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)#define drp(i, st, ed) for (int i = st; i >= ed; i -= 1)#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)#define fill(x, t) memset(x, t, sizeof(x))#define max(x, y) (x)>(y)?(x):(y)#define min(x, y) (x)<(y)?(x):(y)#define ll long long#define db double#define INF 0x3f3f3f3f#define N 100201struct treeNode{int l, r; ll mx, tag;}t[N << 2 | 1];ll w[N], f[N], ls[N], next[N];inline ll read(){    ll x=0,v=1; char ch=getchar();    while (ch<'0'||ch>'9'){if(ch=='-')v=-1; ch=getchar();}    while (ch<='9'&&ch>='0'){x=x*10+ch-'0'; ch=getchar();}    return x*v;}inline void pushDown(int now, int l, int r){    if (!t[now].tag){return ;}    t[now << 1].tag += t[now].tag;    t[now << 1].mx += t[now].tag;    t[now << 1 | 1].tag += t[now].tag;    t[now << 1 | 1].mx += t[now].tag;    t[now].tag = 0;}inline ll query(int now, int l, int r){    if (t[now].l == l && t[now].r == r){        return t[now].mx;    }    pushDown(now, l, r);    int mid = (t[now].l + t[now].r) >> 1;    if (r <= mid){        return query(now << 1, l, r);    }else if (l > mid){        return query(now << 1 | 1, l, r);    }else{        return max(query(now << 1, l, mid), query(now << 1 | 1, mid + 1, r));    }}inline void modify(int now, int l, int r, ll v){    if (t[now].l == l && t[now].r == r){        t[now].tag += v;        t[now].mx += v;        return ;    }    pushDown(now, l, r);    int mid = (t[now].l + t[now].r) >> 1;    if (r <= mid){        modify(now << 1, l, r, v);    }else if (l > mid){        modify(now << 1 | 1, l, r, v);    }else{        modify(now << 1, l, mid, v);        modify(now << 1 | 1, mid + 1, r, v);    }    t[now].mx = max(t[now << 1].mx, t[now << 1 | 1].mx);}inline void build(int now, int l, int r){    t[now] = (treeNode){l, r, 0};    if (l == r){return ;}    int mid = (l + r) >> 1;    build(now << 1, l, mid);    build(now << 1 | 1, mid + 1, r);    t[now].mx = max(t[now << 1].mx, t[now << 1 | 1].mx);}int main(void){    int n = read();    int m = read();    rep(i, 1, n){f[i] = read();}    rep(i, 1, m){w[i] = read();}    rep(i, 1, n){next[i] = n;}    drp(i, n, 1){        next[i] = ls[f[i]];        ls[f[i]] = i;    }    build(1, 1, n);    rep(i, 1, m){        if (ls[i]){            if (next[ls[i]]){                modify(1, ls[i], next[ls[i]] - 1, w[i]);            }else{                modify(1, ls[i], n, w[i]);            }        }    }    ll ans = 0;    rep(i, 1, n){        ans = max(ans, query(1, i, n));        if (next[i]){            modify(1, i, next[i] - 1, -w[f[i]]);            if (next[next[i]]){                modify(1, next[i], next[next[i]] - 1, w[f[i]]);            }else{                modify(1, next[i], n, w[f[i]]);            }        }else{            modify(1, i, n, -w[f[i]]);        }    }    printf("%lld\n", ans);    return 0;}
原创粉丝点击