终于整完ubuntu了开森~
好了进入正体,这题不就跟GSS2差不多嘛,记录一个next[i]表示下一个出现i的位置
然后就各种乱搞啦~
#include <cstdio>
#include <iostream>
using namespace std;
const int MAXN = 1000001;
void read(int &x)
{
x = 0;
char c;
do c = getchar();while (c > '9' || c < '0');
do x = x*10+c-48, c = getchar();while (c >= '0' && c <= '9');
}
int n,m;
int f[MAXN],w[MAXN];
int next[MAXN],last[MAXN];
struct Node
{
int l,r;
long long delta,_max;
};
Node Tree[3*MAXN];
void build(int num,int l,int r)
{
Tree[num].l = l, Tree[num].r = r;
if (l == r) return;
int mid = (l+r)>>1;
build(num<<1,l,mid);
build(num<<1|1,mid+1,r);
}
void update(int num)
{
Node &Lc = Tree[num<<1], &Rc = Tree[num<<1|1];
long long delta = Tree[num].delta;
Lc.delta += delta, Lc._max += delta;
Rc.delta += delta, Rc._max += delta;
Tree[num].delta = 0;
}
void modify(int num,int l,int r,long long delta)
{
if (l <= Tree[num].l && Tree[num].r <= r)
{
Tree[num]._max += delta;
Tree[num].delta += delta;
return;
}
update(num);
int mid = (Tree[num].l+Tree[num].r)>>1;
if (r <= mid) modify(num<<1,l,r,delta);
else if (l > mid) modify(num<<1|1,l,r,delta);
else
{
modify(num<<1,l,r,delta);
modify(num<<1|1,l,r,delta);
}
Tree[num]._max = max(Tree[num<<1]._max,Tree[num<<1|1]._max);
}
int main()
{
read(n);read(m);
for (int i=1;i<=n;i++) read(f[i]);
for (int i=1;i<=m;i++) read(w[i]);
build(1,1,n);
for (int i=n;i>0;i--)
{
next[i] = last[f[i]];
last[f[i]] = i;
}
for (int i=1;i<=m;i++) if (last[i])
{
if (!next[last[i]]) modify(1,last[i],n,w[i]);
else modify(1,last[i],next[last[i]]-1,w[i]);
}
long long ans = 0;
for (int i=1;i<=n;i++)
{
ans = max(ans,Tree[1]._max);
int t = next[i];
if (t)
{
modify(1,i,t-1,-w[f[i]]);
if (next[t]) modify(1,t,next[t]-1,w[f[i]]);
else modify(1,t,n,w[f[i]]);
}
else modify(1,i,n,-w[f[i]]);
}
printf("%lld\n",ans);
return 0;
}