zoukankan      html  css  js  c++  java
  • 【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<=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。

    题解

    线段树经典题

    nxt[i]记录第i天的电影下次播放时间

    枚举区间左端点,线段树维护每个位置作为右端点的答案

    考虑l-r的左端点变为l+1

    发现l到nxt[l]-1的答案减少w[f[l]]

    而nxt[l]到nxt[nxt[l]]-1增加w[f[l]]

    线段树维护,支持区间修改以及查询最大值

    其实记录一段区间直接去修改边,每个数值都加,每个数值都减去。

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<cstdio>
     5 #include<iostream>
     6 #define ll long long
     7 using namespace std;
     8 
     9 int n,m;
    10 int f[1000007],w[1000007],last[1000007],next[1000007];
    11 struct Node
    12 {
    13     ll mx,flag;
    14 }tr[4000007];
    15 
    16 inline void pushdown(int p,int l,int r)
    17 {
    18     if (l==r) return;
    19     ll flag=tr[p].flag;tr[p].flag=0;
    20     tr[p<<1].flag+=flag;tr[p<<1|1].flag+=flag;
    21     tr[p<<1].mx+=flag;tr[p<<1|1].mx+=flag;
    22 //    cout<<flag<<endl;
    23 }
    24 void add(int p,int l,int r,int x,int y,int z)
    25 {
    26     if (tr[p].flag) pushdown(p,l,r);
    27     if (l==x&&r==y)
    28     {
    29         tr[p].flag=z,tr[p].mx+=z;
    30         return;
    31     }
    32     int mid=(l+r)>>1;
    33     if (y<=mid) add(p<<1,l,mid,x,y,z);
    34     else if (x>mid) add(p<<1|1,mid+1,r,x,y,z);
    35     else add(p<<1,l,mid,x,mid,z),add(p<<1|1,mid+1,r,mid+1,y,z);
    36     tr[p].mx=max(tr[p<<1].mx,tr[p<<1|1].mx);
    37 }
    38 int main()
    39 {
    40     scanf("%d%d",&n,&m);
    41     for (int i=1;i<=n;i++)
    42         scanf("%d",&f[i]);
    43     for (int i=1;i<=m;i++)
    44         scanf("%d",&w[i]);
    45     for (int i=n;i>=1;i--)
    46     {
    47         next[i]=last[f[i]];
    48         last[f[i]]=i;
    49     }
    50     for (int i=1;i<=m;i++)
    51     {
    52         if (last[i])
    53             if (!next[last[i]]) add(1,1,n,last[i],n,w[i]);
    54             else add(1,1,n,last[i],next[last[i]]-1,w[i]);
    55     //    for (int j=1;j<=n;j++)
    56         //    cout<<tr[j].mx<<" ";
    57     //    cout<<endl;    
    58     }
    59     ll ans=0;
    60     for (int i=1;i<=n;i++)
    61     {
    62         ans=max(ans,tr[1].mx);
    63         int num=next[i];
    64         if (num)
    65         {
    66             add(1,1,n,i,num-1,-w[f[i]]);
    67             if (next[num]) add(1,1,n,num,next[num]-1,w[f[i]]);
    68             else add(1,1,n,num,n,w[f[i]]);
    69         }
    70         else add(1,1,n,i,n,-w[f[i]]);
    71     }
    72     printf("%lld",ans);
    73 }
  • 相关阅读:
    10条建议帮助你创建更好的jQuery插件
    jQuery的end()方法使用详解
    jquery合并表格中相同文本的相邻单元格
    jQuery动态星级评分效果实现方法
    jQuery过滤HTML标签并高亮显示关键字的方法
    jQuery实现高亮显示网页关键词的方法
    深入.net调用webservice的总结分析
    C#中遍历各类数据集合的方法总结
    asp.net后台cs中的JSON格式变量在前台Js中调用方法(前后台示例代码)
    使用交叉验证对鸢尾花分类模型进行调参(超参数)
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7766213.html
Copyright © 2011-2022 走看看