解题: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
原文地址:https://www.cnblogs.com/ydnhaha/p/9925803.html