• Bzoj3747 [POI1015] 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<=m<=n<=1000000)。
    第二行包含n个整数f[1],f[2],…,f[n](1<=f[i]<=m)。
    第三行包含m个整数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。

    Bzoj权限题。只过了样例,尚未评测。

    题面搬运自神犇hzwer博客。

    线段树维护区间最值,枚举区间起点,不断把起点前面的电影贡献值删去,再把当前电影“从当前直到它下次出现之前”的区间都新加上当前电影的贡献值,不断更新最大答案。

    刚开始按区间加法写的,所以变量用了sum,写到一半发现只搞区间最大值就好,然而懒得改变量名了……

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #define ls l,mid,rt<<1
     7 #define rs mid+1,r,rt<<1|1
     8 #define LL long long
     9 using namespace std;
    10 const int mxn=1000010;
    11 int n,m;
    12 int f[mxn],w[mxn];
    13 int next[mxn],last[mxn];
    14 int cnt[mxn];
    15 struct node{
    16     LL sum;//变量名是sum,实际是存区间最大值 
    17     LL tag;
    18 }t[mxn<<2];
    19 void Build(int l,int r,int rt){//init //实际并没有用到 
    20     if(l==r){
    21         t[rt].sum=t[rt].tag=0;
    22         return;
    23     }
    24     int mid=(l+r)>>1;
    25     Build(ls);Build(rs);
    26     return;
    27 }
    28 void pushdown(int l,int r,int rt){
    29     if(l==r)return;
    30     if(t[rt].tag){ 
    31         int mid=(l+r)>>1;
    32         t[rt<<1].tag+=t[rt].tag;
    33         t[rt<<1|1].tag+=t[rt].tag;
    34         t[rt<<1].sum+=t[rt].tag;
    35         t[rt<<1|1].sum+=t[rt].tag;
    36         t[rt].tag=0;
    37     }
    38 }
    39 void add(int L,int R,int v,int l,int r,int rt){
    40     if(t[rt].tag)pushdown(l,r,rt);
    41     if(L<=l && r<=R){
    42         t[rt].tag+=v;
    43         t[rt].sum+=v;
    44         return;
    45     }
    46     int mid=(l+r)>>1;
    47     if(L<=mid)add(L,R,v,ls);
    48     if(R>mid)add(L,R,v,rs);
    49     t[rt].sum=max(t[rt<<1].sum,t[rt<<1|1].sum);
    50     return;
    51 }
    52 void read(){
    53     scanf("%d%d",&n,&m);
    54     int i,j;
    55     for(i=1;i<=n;i++)scanf("%d",&f[i]);
    56     for(i=1;i<=m;i++)scanf("%d",&w[i]);
    57     return;
    58 }
    59 int main(){
    60     read();
    61     int i,j;
    62     for(i=n;i;i--){
    63         next[i]=last[f[i]];
    64         last[f[i]]=i;
    65     }
    66     for(i=1;i<=m;i++){
    67         if(last[i]){
    68             if(!next[last[i]])add(last[i],n,w[i],1,n,1); 
    69             else add(last[i],next[last[i]]-1,w[i],1,n,1);
    70         }
    71     }
    72     LL ans=0;
    73     for(i=1;i<=n;i++){
    74         ans=max(ans,t[1].sum);
    75         int tmp=next[i];
    76         if(tmp){
    77             add(i,tmp-1,-w[f[i]],1,n,1);
    78             if(next[tmp])add(tmp,next[tmp]-1,w[f[i]],1,n,1); 
    79             else add(tmp,n,w[f[i]],1,n,1);//如果之后没有相同电影了,从next[i]到n的区间都加值 
    80         }
    81         else add(i,n,-w[f[i]],1,n,1);//删除上一个区间的值 
    82     }
    83     printf("%lld",ans);
    84     return 0;
    85 }
  • 相关阅读:
    Flink1.15.0 ON YARN集群安装
    chrome查看页面跳转前请求记录
    Fiddler抓包配置
    基于VUE+OpenSeaDragon的细胞阅片开发
    flutter集成ios和android插件
    ssh报错常用解决方法
    浅析大型网站技术架构的演进
    常用DL算法
    MLDL相关问题收集
    java.lang.IllegalStateException: Ambiguous @ExceptionHandler method mapped for
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/5844114.html
Copyright © 2020-2023  润新知