【线段树】bzoj3747 [POI2015]Kinoman

题解:http://www.cnblogs.com/zyfzyf/p/4105184.html

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 using namespace std;
 5 #define lson rt<<1,l,m
 6 #define rson rt<<1|1,m+1,r
 7 int Num,CH[12],f,c;
 8 inline void R(int &x){
 9     c=0;f=1;
10     for(;c<‘0‘||c>‘9‘;c=getchar())if(c==‘-‘)f=-1;
11     for(x=0;c>=‘0‘&&c<=‘9‘;c=getchar())(x*=10)+=(c-‘0‘);
12     x*=f;
13 }
14 typedef long long ll;
15 int n,m,w[1000001],now[1000001],b[1000001],fa[1000001];
16 ll ans,maxv[4000001],delta[4000001];
17 void pushdown(int rt)
18 {
19     if(delta[rt])
20       {
21         delta[rt<<1]+=delta[rt]; delta[rt<<1|1]+=delta[rt];
22         maxv[rt<<1]+=delta[rt]; maxv[rt<<1|1]+=delta[rt];
23         delta[rt]=0;
24       }
25 }
26 void update(int ql,int qr,int v,int rt,int l,int r)
27 {
28     if(ql<=l&&r<=qr)
29       {
30         delta[rt]+=(ll)v;
31         maxv[rt]+=(ll)v;
32         return;
33       }
34     pushdown(rt); int m=l+r>>1;
35     if(ql<=m) update(ql,qr,v,lson);
36     if(m<qr) update(ql,qr,v,rson);
37     maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
38 }
39 ll query(int qr,int rt,int l,int r)
40 {
41     if(1<=l&&r<=qr) return maxv[rt];
42     pushdown(rt);
43     int m=l+r>>1; ll res=0;
44     if(1<=m) res=max(res,query(qr,lson));
45     if(m<qr) res=max(res,query(qr,rson));
46     return res;
47 }
48 int main()
49 {
50     R(n); R(m);
51     for(int i=1;i<=n;++i) R(b[i]);
52     for(int i=1;i<=m;++i) R(w[i]);
53     for(int i=1;i<=n;++i)
54       {
55           fa[i]=now[b[i]];
56           now[b[i]]=i;
57       }
58     for(int i=1;i<=n;++i)
59       {
60           update(fa[i]+1,i,(ll)w[b[i]],1,1,n);
61           if(fa[i]) update(fa[fa[i]]+1,fa[i],(ll)(-w[b[i]]),1,1,n);
62           ans=max(ans,query(i,1,1,n));
63       } printf("%lld\n",ans);
64     return 0;
65 }
时间: 2024-11-08 20:33:43

【线段树】bzoj3747 [POI2015]Kinoman的相关文章

bzoj3747 [POI2015]Kinoman

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]

【BZOJ3747】[POI2015]Kinoman 线段树

[BZOJ3747][POI2015]Kinoman 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&

【bzoj3747】Kinoman[POI2015](线段树)

题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3747 对于这种题,考虑固定区间的右端点为r,设区间左端点为l能取得的好看值总和为a[l],那么就相当于当r取不同取值时所有al的最大值. 设last[i]表示第i部电影上一次出现的位置,当右端点r右移1位时,因为只有看了一遍的电影能获取好看值,所以能取得f[r]的好看值的al只能是在last[r]~r这个区间.因此每次右移时,last[last[r]]+1~last[r]减去w[f[r

【BZOJ3747】[POI2015]Kinoman【线段树】

[题目链接] 看到数据范围以为是O(n)做法,再看看status似乎带了个log?然后去搜题解,没想到是线段树= =. 题解: 设pre[i]表示与i这个位置上的数相等的前一个数的下标. 用线段树维护答案. 枚举右端点,每次加入一个数,那么pre[i] + 1到i这段位置的答案加上这个数的权值,pre[pre[i]] + 1到pre[i]这段位置的答案减去这个数的权值,然后查询[1, i]的最大值即可. 复杂度: 时间复杂度O(nlogn),空间复杂度O(n). RE: 给线段树开了1倍n的空间

[bzoj3747][POI2015]Kinoman_线段树

Kinoman bzoj-3747 POI-2015 题目大意:有m部电影,第i部电影的好看值为w[i].现在放了n天电影,请你选择一段区间l~r使得l到r之间的好看值总和最大.特别地,如果同一种电影放了两遍及以上,那么这种电影的好看值将不会被获得. 注释:$1\le m \le n \le 10^6$. 想法:和rmq problem类似的,我们处理出每一个位置pos右边第一个和pos上电影种类相同的位置nxt[pos].然后,我从1-n扫一遍,每次讲l+1到nxt[l]-1之间的值加上w[a

BZOJ 3747: [POI2015]Kinoman( 线段树 )

线段树... 我们可以枚举左端点 , 然后用线段树找出所有右端点中的最大值 . ----------------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define rep( i , n ) for( i

【BZOJ 3747】 3747: [POI2015]Kinoman (线段树)

3747: [POI2015]Kinoman Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 830  Solved: 338 Description 共有m部电影,编号为1~m,第i部电影的好看值为w[i]. 在n天之中(从1~n编号)每天会放映一部电影,第i天放映的是第f[i]部. 你可以选择l,r(1<=l<=r<=n),并观看第l,l+1,-,r天内所有的电影.如果同一部电影你观看多于一次,你会感到无聊,于是无法获得这部电影的好看值

3747: [POI2015]Kinoman|线段树

枚举左区间线段树维护最大值 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<vector> #include<cmath> #include<queue> #include<set> #include<map> #define ll l

【BZOJ-3747】Kinoman 线段树

3747: [POI2015]Kinoman Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 715  Solved: 294[Submit][Status][Discuss] Description 共有m部电影,编号为1~m,第i部电影的好看值为w[i]. 在n天之中(从1~n编号)每天会放映一部电影,第i天放映的是第f[i]部. 你可以选择l,r(1<=l<=r<=n),并观看第l,l+1,…,r天内所有的电影.如果同一部电影你观看多