zoukankan      html  css  js  c++  java
  • Bzoj 3747: [POI2015]Kinoman 线段树

    3747: [POI2015]Kinoman

    Time Limit: 60 Sec  Memory Limit: 128 MB
    Submit: 553  Solved: 222
    [Submit][Status][Discuss]

    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。

    HINT

     

    Source

    鸣谢Jcvb

    题解:

    线段树。。。

    用last[]记录每个位置的电影的上一个位置。

    然后从头到尾依次遍历,每次把 (当前位置的电影的上一个位置,当前位置] 这个区间加上当前电影的好看值。然后把 (当前位置的电影的上上一个位置,当前位置的电影的上一个位置] 这个区间减去当前电影的好看值。每次求区间最大值即可。

    这个用线段树维护即可。。。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define INF 1e9
     4 #define LL long long
     5 struct node
     6 {
     7     int left,right;
     8     LL tag,mx;
     9 }tree[4000050];
    10 int f[1000010],w[1000010],last[1000010],pre[1000010];
    11 int read()
    12 {
    13     int s=0,fh=1;char ch=getchar();
    14     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
    15     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
    16     return s*fh;
    17 }
    18 void Build(int k,int l,int r)
    19 {
    20     tree[k].left=l;tree[k].right=r;tree[k].tag=0;tree[k].mx=0;
    21     if(l==r)return;
    22     int mid=(l+r)/2;
    23     Build(k*2,l,mid);Build(k*2+1,mid+1,r);
    24 }
    25 void Pushup(int k)
    26 {
    27     tree[k].mx=max(tree[k*2].mx,tree[k*2+1].mx);
    28 }
    29 void Pushdown(int k)
    30 {
    31     if(tree[k].tag!=0)
    32     {
    33         tree[k*2].tag+=tree[k].tag;
    34         tree[k*2+1].tag+=tree[k].tag;
    35         tree[k*2].mx+=tree[k].tag;
    36         tree[k*2+1].mx+=tree[k].tag;
    37         tree[k].tag=0;
    38     }
    39 }
    40 void Add(int k,int l,int r,int add)
    41 {
    42     if(l<=tree[k].left&&tree[k].right<=r)
    43     {
    44         tree[k].tag+=(LL)add;
    45         tree[k].mx+=(LL)add;
    46         return;
    47     }
    48     Pushdown(k);
    49     int mid=(tree[k].left+tree[k].right)/2;
    50     if(r<=mid)Add(k*2,l,r,add);
    51     else if(l>mid)Add(k*2+1,l,r,add);
    52     else {Add(k*2,l,mid,add);Add(k*2+1,mid+1,r,add);}
    53     Pushup(k);
    54 }
    55 int main()
    56 {
    57     int n,m,i;
    58     LL ans;
    59     n=read();m=read();
    60     for(i=1;i<=n;i++)f[i]=read();
    61     for(i=1;i<=m;i++)w[i]=read();
    62     memset(last,0,sizeof(last));
    63     memset(pre,0,sizeof(pre));
    64     for(i=1;i<=n;i++)
    65     {
    66         last[i]=pre[f[i]];
    67         pre[f[i]]=i;
    68     }
    69     Build(1,1,n);
    70     ans=-INF;
    71     for(i=1;i<=n;i++)
    72     {
    73         Add(1,last[i]+1,i,w[f[i]]);
    74         if(last[i]!=0)
    75         {
    76             Add(1,last[last[i]]+1,last[i],-w[f[i]]);
    77         }
    78         ans=max(ans,tree[1].mx);
    79     }
    80     printf("%lld",ans);
    81     return 0;
    82 }
  • 相关阅读:
    MySQL-简述
    APP测试-Solo Pi工具-性能测试
    APP测试-弱网测试
    iOS 认识runtime 中的三个指针 isa , IMP , SEL
    iOS 什么是函数式编程
    iOS 根据农历日期 获取当前的农历年份 即 干支纪年法算农历年
    iOS 当公司有人向你提问,你该如何应对?
    Mac 环境 下使用Charles 抓包Http/Https请求
    iOS iPhone X 适配启动图片
    iOS11 仿大标题 导航栏
  • 原文地址:https://www.cnblogs.com/Var123/p/5315266.html
Copyright © 2011-2022 走看看