zoukankan      html  css  js  c++  java
  • [BZOJ3747] Kinoman

    问题描述

    共有m部电影,编号为1~m,第i部电影的好看值为w[i]。

    在n天之中(从1~n编号)每天会放映一部电影,第i天放映的是第f[i]部。

    你可以选择l,r(1<=l<=r<=n),并观看第l,l+1,…,r天内所有的电影。如果同一部电影你观看多于一次,你会感到无聊,于是无法获得这部电影的好看值。所以你希望最大化观看且仅观看过一次的电影的好看值的总和。

    输入格式

    第一行两个整数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)。

    输出格式

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

    样例输入

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

    样例输出

    15

    样例解释

    15
    样例解释:

    观看第2,3,4,5,6,7天内放映的电影,其中看且仅看过一次的电影的编号为2,3,4。

    链接

    BZOJ

    解析

    考虑如何解决重复电影没有贡献的问题。记第(i)的电影前面一次出现的时候为(L[i]),后面一次出现的时候为(R[i]),那么这个电影能够计贡献的区间为([i,R[i]-1])。所以,我们把所有电影按照(L[i])排序,然后枚举选择区间的左端点,用线段树维护答案。每次将左端点以前的贡献在线段树中减掉,同时在满足条件的区间中加入(L[i])小于当前左端点的天的贡献。维护最大值即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define N 1000002
    using namespace std;
    struct SegmentTree{
        long long dat,add;
    }t[N*4];
    struct day{
        int l,r,w,p;
    }a[N],b[N];
    int n,m,i,j,k,pos[N],f[N],w[N];
    long long ans;
    int read()
    {
        char c=getchar();
        int w=0;
        while(c<'0'||c>'9') c=getchar();
        while(c<='9'&&c>='0'){
            w=w*10+c-'0';
            c=getchar();
        }
        return w;
    }
    int my_comp(const day &x,const day &y)
    {
        if(x.l==y.l) return x.p<y.p;
        return x.l<y.l;
    }
    void spread(int p)
    {
        if(t[p].add){
            t[p*2].add+=t[p].add;
            t[p*2+1].add+=t[p].add;
            t[p*2].dat+=t[p].add;
            t[p*2+1].dat+=t[p].add;
            t[p].add=0;
        }
    }
    void change(int p,int l,int r,int ql,int qr,int x)
    {
        if(ql<=l&&r<=qr){
            t[p].dat+=x;
            t[p].add+=x;
            return;
        }
        int mid=(l+r)/2;
        spread(p);
        if(ql<=mid) change(p*2,l,mid,ql,qr,x);
        if(qr>mid) change(p*2+1,mid+1,r,ql,qr,x);
        t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    }
    signed main()
    {
        n=read();m=read();
        for(i=1;i<=n;i++) f[i]=read();
        for(i=1;i<=m;i++) w[i]=read();
        for(i=1;i<=n;i++) a[i].w=w[f[i]],a[i].p=i;
        for(i=1;i<=n;i++){
            a[i].l=pos[f[i]];
            pos[f[i]]=i;
        }
        memset(pos,0,sizeof(pos));
        for(i=n;i>=1;i--){
            a[i].r=pos[f[i]]==0?n+1:pos[f[i]];
            pos[f[i]]=i;
        }
        for(i=1;i<=n;i++) b[i]=a[i];
        sort(a+1,a+n+1,my_comp);
        j=k=1;
        for(i=1;i<=n;i++){
            if(i>1) change(1,1,n,b[i-1].p,b[i-1].r-1,-b[i-1].w);
            while(a[j].l<i&&j<=n) change(1,1,n,a[j].p,a[j].r-1,a[j].w),j++;
            ans=max(ans,t[1].dat);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    英文、简繁体中文 IT 词汇对照表
    VB.NET 中的 As New 以及型別指定
    使用 ADO.NET 的 ExecuteScalar 方法返回单一值
    适时调整 SqlDataSource 控件的 DataSourceMode 属性
    ADO.NET 2.0 的并行控制与数据存取冲突侦测
    让 ADO.NET 2.0 的 SqlCommand 和 SqlDataAdapter 合作
    透过 Socket API 让 PDA 和远程 PC 联机
    探讨 .NET 语言的 using statement 与资源释放
    让 user control 中的 Button 也能启用验证
    dotNET 語言中可提升效能的邏輯運算子
  • 原文地址:https://www.cnblogs.com/LSlzf/p/12231520.html
Copyright © 2011-2022 走看看