bzoj3747 [POI2015]Kinoman
阿新 • • 發佈:2017-10-14
ret 無法獲得 name 多說 rip des esc turn getch
輸出觀看且僅觀看過一次的電影的好看值的總和的最大值。
2 3 1 1 4 1 2 4 1
5 3 6 6
樣例解釋:
觀看第2,3,4,5,6,7天內放映的電影,其中看且僅看過一次的電影的編號為2,3,4。
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 42 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 }
bzoj3747 [POI2015]Kinoman