bzoj 3747: [POI2015]Kinoman
来源:互联网 发布:linux cp实现 编辑:程序博客网 时间:2024/04/29 13:00
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
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。
线段树的一眼题。。
枚举右端点。然后维护每个点为左端点的ans
设pre[i]为f[i]上一次出现的位置
则每次枚举一个新的右端点就在[pre[i]+1,i]加w[f[i]]然后[pre[pre[i]]+1,pre[i]]减w[f[i]]就行了
线段树区间修改区间查询 维护区间最大值
#include<cstdio>#include<string>#include<cstring>#include<algorithm>using namespace std;struct tree{ long long m; long long tag;}tr[4000001];inline void build(int p,int l,int r){ if(l!=r) { int mid=(l+r)/2; build(p*2,l,mid); build(p*2+1,mid+1,r); }}inline void push(int p){ if(p>2000000) return ; tr[p*2].m+=tr[p].tag; tr[p*2+1].m+=tr[p].tag; tr[p*2].tag+=tr[p].tag; tr[p*2+1].tag+=tr[p].tag; tr[p].tag=0;}inline void up(int p){ tr[p].m=max(tr[p*2].m,tr[p*2+1].m);}inline void inc(int p,int ll,int rr,int l,int r,long long x){ if(l>r) return ; if(l<=ll&&rr<=r) { tr[p].m+=x; tr[p].tag+=x; } else { push(p); int mid=(ll+rr)/2; if(l<=mid) inc(p*2,ll,mid,l,r,x); if(r>mid) inc(p*2+1,mid+1,rr,l,r,x); up(p); }}inline long long ask(int p,int ll,int rr,int l,int r){ if(l<=ll&&rr<=r) return tr[p].m; else { push(p); int mid=(ll+rr)/2; long long ans=0; if(l<=mid) ans=max(ans,ask(p*2,ll,mid,l,r)); if(r>mid) ans=max(ans,ask(p*2+1,mid+1,rr,l,r)); return ans; }}int f[1000001],la[1000001],pre[1000001];long long w[1000001];int main(){ // freopen("data.in","r",stdin); // freopen("data.out","w",stdout); int n,m; scanf("%d%d",&n,&m); int i; for(i=1;i<=n;i++) scanf("%d",&f[i]); for(i=1;i<=m;i++) scanf("%lld",&w[i]); for(i=1;i<=n;i++) { pre[i]=la[f[i]]; la[f[i]]=i; } build(1,1,n); long long ans=0; int j; for(i=1;i<=n;i++) { inc(1,1,n,pre[i]+1,i,w[f[i]]); inc(1,1,n,pre[pre[i]]+1,pre[i],-w[f[i]]); ans=max(ask(1,1,n,1,i),ans); /*for(j=1;j<=n;j++) printf("%lld ",ask(1,j,j)); printf("\n");*/ } printf("%lld\n",ans); return 0;}
0 0
- bzoj 3747: [POI2015]Kinoman
- BZOJ 3747: [POI2015]Kinoman
- BZOJ 3747: [POI2015]Kinoman
- bzoj 3747 [POI2015]Kinoman
- BZOJ 3747: [POI2015]Kinoman
- BZOJ 3747: [POI2015]Kinoman
- BZOJ 3747 POI2015 Kinoman 线段树
- BZOJ 3747: [POI2015]Kinoman 线段树
- bzoj 3747: [POI2015]Kinoman(线段树)
- 【bzoj 3747】[POI2015]Kinoman(线段树)
- bzoj 3747: [POI2015]Kinoman 线段树
- [BZOJ]3747: [POI2015]Kinoman 线段树
- bzoj 3747 [POI2015]Kinoman 线段树
- 3747: [POI2015]Kinoman
- 3747: [POI2015]Kinoman
- bzoj 3747: [POI2015]Kinoman (线段树+预处理)
- 3747: [POI2015]Kinoman 线段树
- 3747: [POI2015]Kinoman|线段树
- 智能卡操作系统的程序代码结构
- 悲观锁
- 财务记账软件_财务帐套管理软件
- Python_Scrapy_8.爬虫
- HashMap 和 HashTable的区别
- bzoj 3747: [POI2015]Kinoman
- java基础—IO流——复制一个文件到当前文件夹中
- Type B和Type A的区别
- 非root用户启动wireshark抓包
- Ubuntu14.04下Vim的安装与配置
- Javacard---maskgen工具的使用
- 地图的api数据求解
- GDI学习
- Android模拟有道词典