日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ3747: [POI2015]Kinoman

發布時間:2024/4/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ3747: [POI2015]Kinoman 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【傳送門:BZOJ3747】


簡要題意:

  共有m部電影,編號為1到m,第i部電影的好看值為w[i]。

  在n天之中(從1到n編號)每天會放映一部電影,第i天放映的是第f[i]部

  你可以選擇l,r(1<=l<=r<=n),并觀看第l,l+1,…,r天內所有的電影

  如果同一部電影你觀看多于一次,你會感到無聊,于是無法獲得這部電影的好看值

  所以你希望最大化觀看且僅觀看過一次的電影的好看值的總和


題解:

  線段樹

  next[i]表示與第i天播放同一部電影的下一天,如果沒有則為n+1(待會解釋)

  因為如果l,r之間有相同電影,那么這部電影則沒有好看值,所以第i天的電影的好看值只貢獻于第i天到第next[i]-1天(所以為什么上一步next[i]=n+1)

  然后枚舉l,用線段樹維護每一天的好看總值

  枚舉時,先把l到next[l]-1減掉l位置電影的好看值,然后如果next[next[l]]!=0,就把next[l]到next[next[l]]-1加上減掉l位置電影的好看值,然后l++,然后求出l到n的最大值,然后維護整體最大值即可

  注意加long long


參考代碼:

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> using namespace std; typedef long long LL; struct node {int l,r,lc,rc;LL c,lazy; }tr[2100000];int trlen; void bt(int l,int r) {int now=++trlen;tr[now].l=l;tr[now].r=r;tr[now].c=tr[now].lazy=0;tr[now].lc=tr[now].rc=-1;if(l<r){int mid=(l+r)/2;tr[now].lc=trlen+1;bt(l,mid);tr[now].rc=trlen+1;bt(mid+1,r);} } void update(int now) {int lc=tr[now].lc,rc=tr[now].rc;if(lc!=-1){tr[lc].c+=tr[now].lazy;tr[lc].lazy+=tr[now].lazy;}if(rc!=-1){tr[rc].c+=tr[now].lazy;tr[rc].lazy+=tr[now].lazy;}tr[now].lazy=0; } void change(int now,int l,int r,LL c) {if(tr[now].l==l&&tr[now].r==r){tr[now].c+=c;tr[now].lazy+=c;return ;}int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(tr[now].lazy!=0) update(now);if(r<=mid) change(lc,l,r,c);else if(l>mid) change(rc,l,r,c);else change(lc,l,mid,c),change(rc,mid+1,r,c);tr[now].c=max(tr[lc].c,tr[rc].c); } LL findc(int now,int l,int r) {if(tr[now].l==l&&tr[now].r==r) return tr[now].c;int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(r<=mid) return findc(lc,l,r);else if(l>mid) return findc(rc,l,r);else return max(findc(lc,l,mid),findc(rc,mid+1,r)); } int t[1100000],next[1100000]; int ft[1100000],f[1100000]; LL w[1100000]; int main() {int n,m;scanf("%d%d",&n,&m);memset(t,0,sizeof(t));memset(next,0,sizeof(next));memset(ft,0,sizeof(ft));for(int i=1;i<=n;i++){scanf("%d",&f[i]);if(t[f[i]]==0) ft[f[i]]=i;next[t[f[i]]]=i;t[f[i]]=i;}for(int i=1;i<=n;i++) if(next[i]==0) next[i]=n+1;for(int i=1;i<=m;i++) scanf("%lld",&w[i]);trlen=0;bt(1,n);for(int i=1;i<=m;i++) if(ft[i]!=0) change(1,ft[i],next[ft[i]]-1,w[i]);LL ans=findc(1,1,n);int l=1;while(l<n){change(1,l,next[l]-1,-w[f[l]]);if(next[next[l]]!=0) change(1,next[l],next[next[l]]-1,w[f[l]]);l++;ans=max(findc(1,l,n),ans);}printf("%lld\n",ans);return 0; }

?

轉載于:https://www.cnblogs.com/Never-mind/p/8697180.html

總結

以上是生活随笔為你收集整理的BZOJ3747: [POI2015]Kinoman的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。