题目描述

共有\(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:

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

输出样例#1:

  1. 15

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

洛谷P3582(自己写的题解)

代码:

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cctype>
  4. #define ll long long
  5. #define maxn 1000007
  6. #define ls rt<<1
  7. #define rs rt<<1|1
  8. using namespace std;
  9. int n,m,f[maxn],nxt[maxn],last[maxn],a[maxn];
  10. ll ans;
  11. inline int qread() { //快读,不解释……
  12. char c=getchar();int num=0,f=1;
  13. for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
  14. for(;isdigit(c);c=getchar()) num=num*10+c-'0';
  15. return num*f;
  16. }
  17. struct Tree {
  18. ll maxx,lazy;
  19. }tree[maxn<<2];
  20. inline void pushdown(int rt) { //下放lazy标记。
  21. if(tree[rt].lazy) {
  22. tree[ls].lazy+=tree[rt].lazy;
  23. tree[rs].lazy+=tree[rt].lazy;
  24. tree[rs].maxx+=tree[rt].lazy;
  25. tree[ls].maxx+=tree[rt].lazy;
  26. tree[rt].lazy=0;
  27. }
  28. }
  29. void modify(int rt,int l,int r,int L,int R,int val) { //区间修改,用于后面的更新。
  30. if(L>r||R<l) return;
  31. if(L<=l&&r<=R) {
  32. tree[rt].lazy+=val;
  33. tree[rt].maxx+=val;
  34. return;
  35. }
  36. pushdown(rt);
  37. int mid=(l+r)>>1;
  38. modify(ls,l,mid,L,R,val),modify(rs,mid+1,r,L,R,val);
  39. tree[rt].maxx=max(tree[ls].maxx,tree[rs].maxx);
  40. }
  41. int main() {
  42. n=qread(),m=qread();
  43. for(int i=1;i<=n;++i) f[i]=qread();
  44. for(int i=1;i<=m;++i) a[i]=qread();
  45. for(int i=n;i>=1;--i) nxt[i]=last[f[i]],last[f[i]]=i; //处理出nxt和last数组。
  46. for(int i=1;i<=m;++i) {
  47. if(last[i]) { //如果这个电影已经播放过。
  48. int zrj=nxt[last[i]];
  49. if(zrj) modify(1,1,n,last[i],zrj-1,a[i]);
  50. //如果这不是最后一次播放这个电影,那么可以影响到的最右端点是nxt[last[i]]-1,然后last[i]就是左端点,也是第一次看,所以在这个区间加上这个电影的价值。
  51. else modify(1,1,n,last[i],n,a[i]); //如果是最后一次,那么它将一直影响到最后。
  52. }
  53. }
  54. for(int i=1;i<=n;++i) {
  55. ans=max(ans,tree[1].maxx); //每次更新一下最大值。
  56. int zrj=nxt[i];
  57. if(zrj) { //如果第二次播放。
  58. modify(1,1,n,i,zrj-1,-a[f[i]]); //在这次和之后的一次的区间上价值减去这个电影的价值,因为相同电影看了价值为0。
  59. if(nxt[zrj]) modify(1,1,n,zrj,nxt[zrj]-1,a[f[i]]); //第二次和第三次之间加上这个电影的价值(因为是以第二次为左端点,只看了一次)。
  60. else modify(1,1,n,zrj,n,a[f[i]]); //不然就把第二次之后的加上这个价值。
  61. }
  62. else modify(1,1,n,i,n,-a[f[i]]); //没有第二次播放,就从当前时间开始一直到最后,减去这个价值。
  63. }
  64. printf("%lld\n",ans);
  65. return 0;
  66. }

洛谷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. Java读取文件的时候,如何让指针重新回到文件的开头

    今天在测试IO流的使用的时候发现在reader读取文件之后,再向文件添加内容,再继续读文件,打印出的结果只能读取追加的文件. 如何才能重新读取呢?试了mark和reset,似乎会报异常.记在这以后看是 ...

  2. 用JavaScript实现表单按回车自动提交

    JavaScript实现表单form1按回车自动提交代码如下: <script type="text/javascript"> function submitMe() ...

  3. 【leetcode刷题笔记】Gas Station

    There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. You ...

  4. encodeURI,encodeURIComponent编码

    encodeURI().encodeURIComponent().decodeURI().decodeURIComponent() URL编码 Global对象的encodeURI()和encodeU ...

  5. 如何利用pyenv 和virtualenv 在单机上搭建多版本python 虚拟开发环境

    pyenv 和virtualenv分别是干什么的? pyenv帮助你在一台机上建立多个版本的python环境, 并提供方便的切换方法. virtualenv则就是将一个目录建立为一个虚拟的python ...

  6. 【转】 Pro Android学习笔记(三七):Fragment(2):基础小例子

    目录(?)[-] 小例子运行效果 Pre-step一点准备 Step 1Activity的布局 小例子运行效果 这是一个书名和书简介的例子.运行如下图.Activity由左右两个Fragment组成, ...

  7. Springboot监控之一:SpringBoot四大神器之Actuator之2--spring boot健康检查对Redis的连接检查的调整

    因为项目里面用到了redis集群,但并不是用spring boot的配置方式,启动后项目健康检查老是检查redis的时候状态为down,导致注册到eureka后项目状态也是down.问下能不能设置sp ...

  8. mysqladmin命令用法

    mysqladmin 工具的使用格式: mysqladmin [option] command [command option] command ...... option 选项: -c  numbe ...

  9. 2 ubuntu 16.04 安装Elastic Stack

    一: 安装JAVA8          添加ppa sudo add-apt-repository ppa:webupd8team/java sudo apt-get update 安装oracle- ...

  10. Spring MVC配置详解(3)

    一.Spring MVC环境搭建:(Spring 2.5.6 + Hibernate 3.2.0) 1. jar包引入 Spring 2.5.6:spring.jar.spring-webmvc.ja ...