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。

    正解:套路+线段树。

    经典套路不用多说。。

    考虑一下每个点的贡献,记一个电影的上一个播放天为$lst$,下一个播放天为$nxt$。

    那么可以发现,一个点只有在$lst<l$且$r<nxt$的区间才有贡献。

    于是把所有点按照$lst$排序,枚举左端点$l$,维护一个以右端点为下标的线段树,然后每次把$lst<l$的点加入贡献,并把$i<l$的点删除,这些就是区间修改,每次线段树维护全局最大值即可。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 #define N (1000010)
     6 #define ls (x<<1)
     7 #define rs (x<<1|1)
     8 
     9 using namespace std;
    10 
    11 int lst[N],nxt[N],q[N],f[N],w[N],cnt[N],n,m;
    12 ll sum[N<<2],tag[N<<2],ans;
    13 
    14 il int gi(){
    15   RG int x=0,q=1; RG char ch=getchar();
    16   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    17   if (ch=='-') q=-1,ch=getchar();
    18   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    19   return q*x;
    20 }
    21 
    22 il int cmp(const int &a,const int &b){ return lst[a]<lst[b]; }
    23 
    24 il void pushdown(RG int x){
    25   sum[ls]+=tag[x],sum[rs]+=tag[x];
    26   tag[ls]+=tag[x],tag[rs]+=tag[x];
    27   tag[x]=0; return;
    28 }
    29 
    30 il void update(RG int x,RG int l,RG int r,RG int xl,RG int xr,RG int v){
    31   if (xl<=l && r<=xr){ sum[x]+=v,tag[x]+=v; return; }
    32   if (tag[x]) pushdown(x); RG int mid=(l+r)>>1;
    33   if (xr<=mid) update(ls,l,mid,xl,xr,v);
    34   else if (xl>mid) update(rs,mid+1,r,xl,xr,v);
    35   else update(ls,l,mid,xl,mid,v),update(rs,mid+1,r,mid+1,xr,v);
    36   sum[x]=max(sum[ls],sum[rs]); return;
    37 }
    38 
    39 int main(){
    40 #ifndef ONLINE_JUDGE
    41   freopen("kinoman.in","r",stdin);
    42   freopen("kinoman.out","w",stdout);
    43 #endif
    44   n=gi(),m=gi();
    45   for (RG int i=1;i<=n;++i)
    46     q[i]=i,f[i]=gi(),nxt[cnt[f[i]]]=i,lst[i]=cnt[f[i]],nxt[i]=n+1,cnt[f[i]]=i;
    47   for (RG int i=1;i<=m;++i) w[i]=gi(); sort(q+1,q+n+1,cmp);
    48   for (RG int l=1,pos=1;l<=n;++l){
    49     for (RG int x=q[pos];pos<=n && lst[x]<l && x>=l;++pos,x=q[pos])
    50       update(1,1,n,x,nxt[x]-1,w[f[x]]);
    51     if (l>1) update(1,1,n,l-1,nxt[l-1]-1,-w[f[l-1]]); ans=max(ans,sum[1]);
    52   }
    53   cout<<ans; return 0;
    54 }
  • 相关阅读:
    人月神话 画蛇添足
    人月神话 贵族专制和民主政治
    人月神话 外科手术队伍
    人月神话 焦油坑
    体温填报(五)
    体温填报(四)
    qwb与学姐
    qwb VS 去污棒
    1045 快速排序(25 分)
    LibreOJ #107. 维护全序集
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7649846.html
Copyright © 2011-2022 走看看