BZOJ3747 POI2015 Kinoman


Description

共有m部电影,编号为1~m,第i部电影的好看值为w[i]。

在n天之中(从1~n编号)每天会放映一部电影,第i天放映的是第f[i]部。

你可以选择l,r(1<=l<=r<=n),并观看第l,l+1,…,r天内所有的电影。如果同一部电影你观看多于一次,你会感到无聊,于是无法获得这部电影的好看值。所以你希望最大化观看且仅观看过一次的电影的好看值的总和。

Input

第一行两个整数n,m(1&lt;=m&lt;=n&lt;=1000000)" role="presentation">n,m(1<=m<=n<=1000000)n,m(1<=m<=n<=1000000)。

第二行包含n个整数f[1],f[2],…,f[n](1&lt;=f[i]&lt;=m)" role="presentation">f[1],f[2],…,f[n](1<=f[i]<=m)f[1],f[2],…,f[n](1<=f[i]<=m)。

第三行包含m个整数w[1],w[2],…,w[m](1&lt;=w[j]&lt;=1000000)" role="presentation">w[1],w[2],…,w[m](1<=w[j]<=1000000)w[1],w[2],…,w[m](1<=w[j]<=1000000)。

Output

输出观看且仅观看过一次的电影的好看值的总和的最大值。

Sample Input

9 4

2 3 1 1 4 1 2 4 1

5 3 6 6

Sample Output

15

样例解释:

观看第2,3,4,5,6,7天内放映的电影,其中看且仅看过一次的电影的编号为2,3,4。


线段树可以维护的真的不只是线段,区间信息什么的,或者时间以及各种维度

只有你想不到没有线段树维护不了的

这道题就是线段树小技巧的运用,自己也是看了题解才做出来的

我们先考虑全局状态,假设当前我们知道一个区间[l,r]" role="presentation">[l,r][l,r]的答案,那么我们考虑怎么把l向右移动一位,也就是在区间中减少一次f[l]" role="presentation">f[l]f[l]的出现次数

如果我们对于一个l,同时维护它对应的所有的r的答案呢?

我们发现,答案的变化之和下一个f[l]" role="presentation">f[l]f[l]的位置有关

所以我们可以预处理一下nxt[l]" role="presentation">nxt[l]nxt[l]表示下一个颜色和l相同的位置

那么我们可以发现,删掉一个l之后l nxt[l]−1" role="presentation">l nxt[l]−1l nxt[l]−1的答案增加了w[l]" role="presentation">w[l]w[l]

nxt[l] nxt[nxt[l]]" role="presentation">nxt[l] nxt[nxt[l]]nxt[l] nxt[nxt[l]]的答案增加了w[l]" role="presentation">w[l]w[l]

当然还需要判断一下边界什么的

细节最好自己思考清楚


#include<bits/stdc++.h>
using namespace std;
#define LD (t<<1)
#define RD (t<<1|1)
#define N 1000010
#define LL long long
LL maxv[N<<2],add[N<<2];
int n,m,f[N],w[N],nxt[N],last[N],vl[N];
void pushdown(int t){
if(add[t]){
add[LD]+=add[t];maxv[LD]+=add[t];
add[RD]+=add[t];maxv[RD]+=add[t];
add[t]=0;
}
}
void pushup(int t){maxv[t]=max(maxv[LD],maxv[RD]);}
void build(int t,int l,int r){
if(l>=r)return;
int mid=(l+r)>>1;
build(LD,l,mid);
build(RD,mid+1,r);
pushup(t);
}
void modify(int t,int l,int r,int L,int R,int val){
if(l>r)return;
if(L<=l&&r<=R){add[t]+=val;maxv[t]+=val;return;}
pushdown(t);
int mid=(l+r)>>1;
if(R<=mid)modify(LD,l,mid,L,R,val);
else if(L>mid)modify(RD,mid+1,r,L,R,val);
else{
modify(LD,l,mid,L,mid,val);
modify(RD,mid+1,r,mid+1,R,val);
}
pushup(t);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&f[i]);
for(int i=1;i<=m;i++)scanf("%d",&w[i]);
for(int i=n;i>=1;i--)nxt[i]=last[f[i]],last[f[i]]=i;
for(int i=1;i<=m;i++)
if(last[i]){
if(!nxt[last[i]])modify(1,1,n,last[i],n,w[i]);
else modify(1,1,n,last[i],nxt[last[i]]-1,w[i]);
}
LL ans=0;
for(int i=1;i<=n;i++){
ans=max(ans,maxv[1]);
if(!nxt[i])modify(1,1,n,i,n,-w[f[i]]);
else{
modify(1,1,n,i,nxt[i]-1,-w[f[i]]);
if(nxt[nxt[i]])modify(1,1,n,nxt[i],nxt[nxt[i]]-1,w[f[i]]);
else modify(1,1,n,nxt[i],n,w[f[i]]);
}
}
printf("%lld",ans);
return 0;
}

BZOJ3747 POI2015 Kinoman 【线段树】*的更多相关文章

  1. BZOJ3747:[POI2015]Kinoman(线段树)

    Description 共有m部电影,编号为1~m,第i部电影的好看值为w[i]. 在n天之中(从1~n编号)每天会放映一部电影,第i天放映的是第f[i]部. 你可以选择l,r(1<=l< ...

  2. 【BZOJ3747】[POI2015]Kinoman 线段树

    [BZOJ3747][POI2015]Kinoman Description 共有m部电影,编号为1~m,第i部电影的好看值为w[i]. 在n天之中(从1~n编号)每天会放映一部电影,第i天放映的是第 ...

  3. 【bzoj3747】[POI2015]Kinoman 线段树区间合并

    题目描述 一个长度为n的序列,每个数为1~m之一.求一段连续子序列,使得其中之出现过一次的数对应的价值之和最大. 输入 第一行两个整数n,m(1<=m<=n<=1000000). 第 ...

  4. 【bzoj3747】[POI2015]Kinoman - 线段树(经典)

    Description 共有m部电影,编号为1~m,第i部电影的好看值为w[i]. 在n天之中(从1~n编号)每天会放映一部电影,第i天放映的是第f[i]部. 你可以选择l,r(1<=l< ...

  5. [bzoj3747][POI2015]Kinoman_线段树

    Kinoman bzoj-3747 POI-2015 题目大意:有m部电影,第i部电影的好看值为w[i].现在放了n天电影,请你选择一段区间l~r使得l到r之间的好看值总和最大.特别地,如果同一种电影 ...

  6. Bzoj 3747: [POI2015]Kinoman 线段树

    3747: [POI2015]Kinoman Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 553  Solved: 222[Submit][Stat ...

  7. 【BZOJ-3747】Kinoman 线段树

    3747: [POI2015]Kinoman Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 715  Solved: 294[Submit][Stat ...

  8. 3747: [POI2015]Kinoman|线段树

    枚举左区间线段树维护最大值 #include<algorithm> #include<iostream> #include<cstdlib> #include< ...

  9. BZOJ_3747_[POI2015]Kinoman_线段树

    BZOJ_3747_[POI2015]Kinoman_线段树 Description 共有m部电影,编号为1~m,第i部电影的好看值为w[i]. 在n天之中(从1~n编号)每天会放映一部电影,第i天放 ...

随机推荐

  1. LA 7272 Promotions(dfs)

    https://vjudge.net/problem/UVALive-7272 题意: 公司要提拔人,现在有n个人,现在有m条有向边,A->B表示A的表现比B好,也就是如果B晋升了,那么A肯定会 ...

  2. 使用IP spoofer 功能

    有个问题请教:使用IP spoofer 功能后,很多vuser都会挂掉,这个怎么解决呢? LR

  3. 机器学习笔记—Logistic 回归

    前面我们介绍了线性回归,为捕获训练集中隐藏的线性模型,提高预测准确率,我们寻找最佳参数 θ,使得预测值与真实值误差尽量小,也就是使均方误差最小.而经过验证,最小均方误差是符合最大似然估计理论的. 在 ...

  4. JavaScript权威指南--类型、值和变量

    本章要点图 数据类型:计算机程序的运行需要对值(value)比如数字3.14或者文本"hello world"进行操作,在编程语言中,能够表示并操作的值的类型叫做数据类型(type ...

  5. js事件在不同浏览器之间的差异

    目录: 1. 介绍 2. 不同浏览器之间的差异 2.1 添加事件的方法 2.2 事件对象event 2.3 event中的属性/方法 3. 总结 1. 介绍 javascript与HTML之间的交互是 ...

  6. 利用python3.x实现小爬虫下载贴吧内图片

    Hi, I'm back.   寒假在家只有一台笔记本,也懒得把台式机上的键盘拆下来用,因此编程被我暂时搁置,转而在网易云课堂上学了一下Python.可惜的是云课堂的Python教程是基于Python ...

  7. Android面试三之Service

    Service是什么 Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件.其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行.另 ...

  8. 【Error】local variable 'xxx' referenced before assignment

    此种错误涉及到变量的作用域,即全局变量和局部变量的操作. 总结如下: 内部函数,不修改全局变量可以访问全局变量 内部函数,修改同名全局变量,则python会认为它是一个局部变量 在内部函数修改同名全局 ...

  9. Codeforces命令行工具

    https://github.com/xalanq/cf-tool Codeforces Tool 是 Codeforces 的命令行界面的工具. 这玩意儿挺快.挺小.挺强大,还跨平台哦. 特点 提交 ...

  10. Linux系统下第三方软件安装实例

    在第三方软件安装的时候,首先要有自己的rpm安装包!然后要有可以使用的yum源(前面有关于yum源的介绍) 一.安装wps步骤如下: 1)首先进入安装包所在目录,并查看有没有要安装的软件 2)然后,对 ...