• 【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],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

    Sample Output

    15
    样例解释:
    观看第2,3,4,5,6,7天内放映的电影,其中看且仅看过一次的电影的编号为2,3,4。

    题解:还是用到这一个思路:每个子串都是一个前缀的后缀,那么我们枚举每个前缀,然后用线段树维护它的每个后缀的答案即可。

    具体地,如果当前位置是i,i的前缀是pre[i],那么在(pre[i],i]中的后缀的和都会加上w;还要减掉原来pre[i]的权值,即在(pre[pre[i]],pre[i]]里的后缀都要减去w。再用线段树查询最大值即可。

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    typedef long long ll;
    const int maxn=1000010;
    int n,m;
    ll ans;
    int w[maxn],f[maxn],pre[maxn],last[maxn];
    ll s[maxn<<2],tag[maxn<<2];
    void updata(int l,int r,int x,int a,int b,ll val)
    {
    	if(a<=l&&r<=b)
    	{
    		s[x]+=val,tag[x]+=val;
    		return ;
    	}
    	if(tag[x])	s[lson]+=tag[x],tag[lson]+=tag[x],s[rson]+=tag[x],tag[rson]+=tag[x],tag[x]=0;
    	int mid=(l+r)>>1;
    	if(a<=mid)	updata(l,mid,lson,a,b,val);
    	if(b>mid)	updata(mid+1,r,rson,a,b,val);
    	s[x]=max(s[lson],s[rson]);
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	n=rd(),m=rd();
    	int i;
    	for(i=1;i<=n;i++)	f[i]=rd(),pre[i]=last[f[i]],last[f[i]]=i;
    	for(i=1;i<=m;i++)	w[i]=rd();
    	for(i=1;i<=n;i++)
    	{
    		updata(1,n,1,pre[i]+1,i,w[f[i]]);
    		if(pre[i])	updata(1,n,1,pre[pre[i]]+1,pre[i],-w[f[i]]);
    		ans=max(ans,s[1]);
    	}
    	printf("%lld",ans);
    	return 0;
    }
  • 相关阅读:
    POJ1094查分约束,判断关系是否唯一
    POJ1087DFS+匈牙利或者DINIC
    POJ1087DFS+匈牙利或者DINIC
    #Leetcode# 34. Find First and Last Position of Element in Sorted Array
    #Leetcode# 18. 4Sum
    #Leetcode# 16. 3Sum Closest
    #Leetcode# 15. 3Sum
    #Leetcode# 42. Trapping Rain Water
    #Leetcode# 63. Unique Paths II
    #Leetcode# 62. Unique Paths
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7514489.html
Copyright © 2020-2023  润新知