题目描述

共有\(m\)部电影,编号为\(1——m\),第\(i\)部电影的好看值为\(w[i]\)。在\(n\)天之中(从\(1~n\)编号)每天会放映一部电影,第\(i\)天放映的是第\(f[i]\)部。你可以选择\(l,r(1 \leq l \leq r \leq n)\),并观看第\(l,l+1,…,r\)天内所有的电影。如果同一部电影你观看多于一次,你会感到无聊,于是无法获得这部电影的好看值。所以你希望最大化观看且仅观看过一次的电影的好看值的总和。

输入输出格式

输入格式:

第一行两个整数\(n,m(1 \leq m \leq n \leq 1000000)\)。第二行包含\(n\)个整数\(f[1],f[2],…,f[n]\)。第三行包含\(m\)个整数\(w[1],w[2],…,w[m]\)。

输出格式:

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

输入输出样例

输入样例#1:

9 4
2 3 1 1 4 1 2 4 1
5 3 6 6

输出样例#1:

15

思路:这道题目我们可以考虑先记录每种电影上一次开播时间和下一次开播时间(即以下代码中的\(last\)数组和\(nxt\)数组),然后对于每种电影,我们可以先处理中它是否播放过对后面区间的影响情况,然后再对\(n\)个时间点分别考虑,我们可以枚举左端点,然后根据左端点电影的播放情况就可以确定它可以影响到的最右端点,然后不断更新,更新过程中记录最大值,最后那个最大值即为答案。

洛谷P3582(自己写的题解)

代码:

#include<cstdio>
#include<algorithm>
#include<cctype>
#define ll long long
#define maxn 1000007
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
int n,m,f[maxn],nxt[maxn],last[maxn],a[maxn];
ll ans;
inline int qread() { //快读,不解释……
char c=getchar();int num=0,f=1;
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) num=num*10+c-'0';
return num*f;
}
struct Tree {
ll maxx,lazy;
}tree[maxn<<2];
inline void pushdown(int rt) { //下放lazy标记。
if(tree[rt].lazy) {
tree[ls].lazy+=tree[rt].lazy;
tree[rs].lazy+=tree[rt].lazy;
tree[rs].maxx+=tree[rt].lazy;
tree[ls].maxx+=tree[rt].lazy;
tree[rt].lazy=0;
}
}
void modify(int rt,int l,int r,int L,int R,int val) { //区间修改,用于后面的更新。
if(L>r||R<l) return;
if(L<=l&&r<=R) {
tree[rt].lazy+=val;
tree[rt].maxx+=val;
return;
}
pushdown(rt);
int mid=(l+r)>>1;
modify(ls,l,mid,L,R,val),modify(rs,mid+1,r,L,R,val);
tree[rt].maxx=max(tree[ls].maxx,tree[rs].maxx);
}
int main() {
n=qread(),m=qread();
for(int i=1;i<=n;++i) f[i]=qread();
for(int i=1;i<=m;++i) a[i]=qread();
for(int i=n;i>=1;--i) nxt[i]=last[f[i]],last[f[i]]=i; //处理出nxt和last数组。
for(int i=1;i<=m;++i) {
if(last[i]) { //如果这个电影已经播放过。
int zrj=nxt[last[i]];
if(zrj) modify(1,1,n,last[i],zrj-1,a[i]);
//如果这不是最后一次播放这个电影,那么可以影响到的最右端点是nxt[last[i]]-1,然后last[i]就是左端点,也是第一次看,所以在这个区间加上这个电影的价值。
else modify(1,1,n,last[i],n,a[i]); //如果是最后一次,那么它将一直影响到最后。
}
}
for(int i=1;i<=n;++i) {
ans=max(ans,tree[1].maxx); //每次更新一下最大值。
int zrj=nxt[i];
if(zrj) { //如果第二次播放。
modify(1,1,n,i,zrj-1,-a[f[i]]); //在这次和之后的一次的区间上价值减去这个电影的价值,因为相同电影看了价值为0。
if(nxt[zrj]) modify(1,1,n,zrj,nxt[zrj]-1,a[f[i]]); //第二次和第三次之间加上这个电影的价值(因为是以第二次为左端点,只看了一次)。
else modify(1,1,n,zrj,n,a[f[i]]); //不然就把第二次之后的加上这个价值。
}
else modify(1,1,n,i,n,-a[f[i]]); //没有第二次播放,就从当前时间开始一直到最后,减去这个价值。
}
printf("%lld\n",ans);
return 0;
}

洛谷P3582 [POI2015]KIN的更多相关文章

  1. BZOJ 4385 洛谷3594 POI2015 WIL-Wilcze doły

    [题解] 手残写错调了好久QAQ...... 洛谷的数据似乎比较水.. n个正整数!!这很重要 这道题是个类似two pointer的思想,外加一个单调队列维护当前区间内长度为d的子序列中元素之和的最 ...

  2. 洛谷 P3586 [POI2015]LOG

    P3586 [POI2015]LOG 题目描述 维护一个长度为n的序列,一开始都是0,支持以下两种操作:1.U k a 将序列中第k个数修改为a.2.Z c s 在这个序列上,每次选出c个正数,并将它 ...

  3. 洛谷P3588 - [POI2015]Pustynia

    Portal Description 给定一个长度为\(n(n\leq10^5)\)的正整数序列\(\{a_n\}\),每个数都在\([1,10^9]\)范围内,告诉你其中\(s\)个数,并给出\(m ...

  4. 洛谷 P3585 [POI2015]PIE

    P3585 [POI2015]PIE 题目描述 一张n*m的方格纸,有些格子需要印成黑色,剩下的格子需要保留白色.你有一个a*b的印章,有些格子是凸起(会沾上墨水)的.你需要判断能否用这个印章印出纸上 ...

  5. 洛谷P3588 [POI2015]PUS

    题面 sol:说了是线段树优化建图的模板... 就是把一整个区间的点连到一个点上,然后用那个点来连需要连一整个区间的点就可以了,就把边的条数优化成n*log(n)了 #include <queu ...

  6. 洛谷P3586 [POI2015]LOG(贪心 权值线段树)

    题意 题目链接 Sol 显然整个序列的形态对询问没什么影响 设权值\(>=s\)的有\(k\)个. 我们可以让这些数每次都被选择 那么剩下的数,假设值为\(a_i\)次,则可以\(a_i\)次被 ...

  7. 洛谷P3588 [POI2015]PUS(线段树优化建图)

    题面 传送门 题解 先考虑暴力怎么做,我们把所有\(r-l+1-k\)中的点向\(x\)连有向边,表示\(x\)必须比它们大,那么如果这张图有环显然就无解了,否则的话我们跑一个多源最短路,每个点的\( ...

  8. 洛谷P3585 [POI2015]PIE

    传送门 题目大意:有个n*m的格子图,要求'x'点要被染成黑色 有个a*b的印章,'x'是可以染色的印章上的点. 要求用印章去染色格子 (1)印章不可以旋转. (2)不能把墨水印到纸外面. (3)纸上 ...

  9. BZOJ 3747 洛谷 3582 [POI2015]Kinoman

    [题解] 扫描线+线段树. 我们记第i部电影上次出现的位置是$pre[i]$,我们从$1$到$n$扫描,每次区间$(pre[i],i]$加上第i部电影的贡献$w[f[i]]$,区间$[pre[pre[ ...

随机推荐

  1. (转)#ifndef的用法

    原文链接:http://wenku.baidu.com/link?url=c4doqVo3U429RkwTN5eaJIfD2rEu-1bLKKQXuqO8drmL359PhUjVmzC7P94wBY9 ...

  2. Ffmpeg移植S3C2440

    Ffmpeg移植过程: FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证.它的移植同样遵循LGPL或GPL移植方法:configure.make.make ...

  3. ACM学习历程—UESTC 1217 The Battle of Chibi(递推 && 树状数组)(2015CCPC C)

    题目链接:http://acm.uestc.edu.cn/#/problem/show/1217 题目大意就是求一个序列里面长度为m的递增子序列的个数. 首先可以列出一个递推式p(len, i) =  ...

  4. 2017.10.6北京清北综合强化班DAY6

    题目大意:改变一个数的位置 把一个序列变成不下降序列 题解: 设置一个pre,如果破坏单调性,就把‘删除’这个.否则把pre修改为当前元素的值. 考试时这样得了90分,是因为我的做法只能过这样的数据 ...

  5. 【C++ Primer 5th】Chapter 1

    1. 每个C++都包含至少一个函数,其中一个必须为main函数,且 main 函数的返回类型必须为 int. 2. 函数定义包括:返回类型,函数名,形参列表,函数体 3. main 函数返回值用来指示 ...

  6. 【转】 Pro Android学习笔记(七二):HTTP服务(6):HttpURLConnection

    目录(?)[-] Http Get的使用方式 基础小例子 Cookie的使用 重定向 HTTP POST的小例子 基础小例子 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件,转载 ...

  7. ceph学习之CRUSH

    CRUSH的全称是Controlled Replication Under Scalable Hashing,是ceph数据存储的分布式选择算法,也是ceph存储引擎的核心.在之前的博客里介绍过,ce ...

  8. Linker Tools Error LNK2001

    https://msdn.microsoft.com/en-us/library/f6xx1b1z.aspx https://www.cnblogs.com/runningRain/p/5674833 ...

  9. T-SQL 高级编程

    在Sql Server 中访问数据库一般有2种方式: 1.一种是使用应用程序编程接口API 2.数据库语句 变量:局部变量:以@为前缀,如@Age:全局变量以@@为前缀:(Ps:全局变量以系统定义和维 ...

  10. Python 图像识别入门篇

    一.安装Python依赖 pip install pytesseract pyocr pillow Image pip安装:https://www.cnblogs.com/Javame/p/10918 ...