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 }
  • 相关阅读:
    POJ 3114 Tarjan+Dijkstra
    278. First Bad Version
    209. Minimum Size Subarray Sum
    154. Find Minimum in Rotated Sorted Array II
    153. Find Minimum in Rotated Sorted Array
    710. Random Pick with Blacklist
    767. Reorganize String
    524. Longest Word in Dictionary through Deleting
    349. Intersection of Two Arrays
    350. Intersection of Two Arrays II
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7649846.html
Copyright © 2011-2022 走看看