共有m部电影,编号为1~m,第i部电影的好看值为w[i]。
在n天之中(从1~n编号)每天会放映一部电影,第i天放映的是第f[i]部。
你可以选择l,r(1<=l<=r<=n),并观看第l,l+1,…,r天内所有的电影。如果同一部电影你观看多于一次,你会感到无聊,于是无法获得这部电影的好看值。所以你希望最大化观看且仅观看过一次的电影的好看值的总和。
标签:
#include<cstdio>
#include<iostream>
#define LL long long
using namespace std;
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
int w[1000010],f[1000010];
int lst[1000010],nxt[1000010];
int n,m;
LL ans;
struct segtree{int l,r;LL tag,mx;}tree[4000010];
inline void pushdown(int k)
{
if (tree[k].l==tree[k].r)return;
LL tag=tree[k].tag;tree[k].tag=0;
if (tag)
{
tree[k<<1].mx+=tag;
tree[k<<1].tag+=tag;
tree[k<<1|1].mx+=tag;
tree[k<<1|1].tag+=tag;
}
}
inline void buildtree(int now,int l,int r)
{
tree[now].l=l;tree[now].r=r;
if (l==r)return;
int mid=(l+r)>>1;
buildtree(now<<1,l,mid);
buildtree(now<<1|1,mid+1,r);
}
inline void add(int now,int x,int y,int d)
{
if (tree[now].tag)pushdown(now);
int l=tree[now].l,r=tree[now].r;
if (l==x&&r==y)
{
tree[now].tag+=d;
tree[now].mx+=d;
return;
}
int mid=(l+r)>>1;
if (y<=mid)add(now<<1,x,y,d);
else if (x>mid)add(now<<1|1,x,y,d);
else
{
add(now<<1,x,mid,d);
add(now<<1|1,mid+1,y,d);
}
tree[now].mx=max(tree[now<<1].mx,tree[now<<1|1].mx);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)f[i]=read();
for(int i=1;i<=m;i++)w[i]=read();
for (int i=n;i>=1;i--)
{
nxt[i]=lst[f[i]];
lst[f[i]]=i;
}
buildtree(1,1,n);
for(int i=1;i<=m;i++)
if (lst[i])
{
if (!nxt[lst[i]])add(1,lst[i],n,w[i]);
else add(1,lst[i],nxt[lst[i]]-1,w[i]);
}
for (int i=1;i<=n;i++)
{
ans=max(ans,tree[1].mx);
int to=nxt[i];
if (to)
{
add(1,i,to-1,-w[f[i]]);
if (nxt[to])add(1,to,nxt[to]-1,w[f[i]]);
else add(1,to,n,w[f[i]]);
}else add(1,i,n,-w[f[i]]);
}
printf("%lld\n",ans);
return 0;
}
标签:
原文地址:http://www.cnblogs.com/zhber/p/4175810.html