zoukankan      html  css  js  c++  java
  • 解题:POI 2015 Kinoman

    题面

    发现每种电影只在两场之间产生贡献(只有$pos$的一场的就在$[pos,n]$产生贡献)。那么我们针对每个位置$i$求出这场电影下一次出现的位置$nxt[i]$,然后每次更新一下,求整个区间的最大值。具体说来我们先在每个电影第一次上映的位置$i$对$[i,nxt[i]-1]$区间修改一下,然后从左到右扫过去,每次消除$[i,nxt[i]-1]$的贡献,再增加$[nxt[i],nxt[nxt[i]]-1]$的贡献即可。

    注意:不一定每种电影都出现过!

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=1000005;
     6 long long maxx[4*N],laz[4*N],ans;
     7 int num[N],val[N],fir[N],las[N],nxt[N],n,m,rr;
     8 void release(int nde)
     9 {
    10     if(laz[nde])
    11     {
    12         int ls=2*nde,rs=2*nde+1;
    13         laz[ls]+=laz[nde],laz[rs]+=laz[nde];
    14         maxx[ls]+=laz[nde],maxx[rs]+=laz[nde];
    15         laz[nde]=0;
    16     }
    17 }
    18 void add(int nde,int l,int r,int nl,int nr,int task)
    19 {
    20     if(l>nr||r<nl)
    21         return ;
    22     else if(l>=nl&&r<=nr)
    23         maxx[nde]+=task,laz[nde]+=task;
    24     else
    25     {
    26         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde);
    27         add(ls,l,mid,nl,nr,task),add(rs,mid+1,r,nl,nr,task);
    28         maxx[nde]=max(maxx[ls],maxx[rs]);
    29     }
    30 }
    31 long long query(int nde,int l,int r,int nl,int nr)
    32 {
    33     if(l>nr||r<nl)
    34         return 0;
    35     else if(l>=nl&&r<=nr)
    36         return maxx[nde];
    37     else
    38     {
    39         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde);
    40         return max(query(ls,l,mid,nl,nr),query(rs,mid+1,r,nl,nr));
    41     }
    42 }
    43 int main ()
    44 {
    45     scanf("%d%d",&n,&m);
    46     for(int i=1;i<=n;i++)
    47     {
    48         scanf("%d",&num[i]);
    49         if(las[num[i]]) 
    50             nxt[las[num[i]]]=i;
    51         las[num[i]]=i;
    52     }
    53     for(int i=n;i;i--) 
    54         fir[num[i]]=i;
    55     for(int i=1;i<=m;i++) 
    56         scanf("%d",&val[i]);
    57     for(int i=1;i<=m;i++)
    58         if(fir[i])
    59         {
    60             rr=nxt[fir[i]]?nxt[fir[i]]-1:n;
    61             add(1,1,n,fir[i],rr,val[i]);
    62         }
    63     for(int i=1;i<=n;i++)
    64     {
    65         ans=max(ans,maxx[1]);
    66         rr=nxt[i]?nxt[i]-1:n;
    67         add(1,1,n,i,rr,-val[num[i]]);
    68         if(nxt[i])
    69         {
    70             rr=nxt[nxt[i]]?nxt[nxt[i]]-1:n;
    71             add(1,1,n,nxt[i],rr,val[num[i]]);
    72         }
    73     }
    74     printf("%lld",ans);
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    LeetCode之移除元素
    有被开心到hh(日常)
    交换排序
    插入排序
    顺序查找&折半查找
    C++之引用
    MySQL学习笔记
    C/C++程序编译过程
    计算机面试知识整合(更新中...)
    MFC之编辑框
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/9925803.html
Copyright © 2011-2022 走看看