zoukankan      html  css  js  c++  java
  • 【bzoj3747】[POI2015]Kinoman 线段树区间合并

    题目描述

    一个长度为n的序列,每个数为1~m之一。求一段连续子序列,使得其中之出现过一次的数对应的价值之和最大。

    输入

    第一行两个整数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)。

    输出

    输出观看且仅观看过一次的电影的好看值的总和的最大值。

    样例输入

    9 4
    2 3 1 1 4 1 2 4 1
    5 3 6 6

    样例输出

    15


    题解

    线段树区间合并

    考虑从左到右添加数的过程:选出的以该数为右端点的连续子序列中,该数的贡献为w[a[i]],该数上一个相同的数的贡献为-w[a[i]](因为选择了该数就会重复,需要把该数的贡献减掉),再前面相同的数的贡献为0。

    于是可以使用线段树实现单点修改和查询最大连续子段和(实际上是1~i的最大包含右端点连续子段和,但是考虑到如果最大连续子段和不包含右端点,那么以前它的贡献不会更差,因此无需讨论以前的贡献)。

    时间复杂度为$O(nlog n)$。由于空间原因,数组不能无脑开到4倍,需要开$3.5*10^6$可过。

    #include <cstdio>
    #include <algorithm>
    #define N 1000010
    #define M 3500010
    using namespace std;
    int pos[N] , last[N] , v[N] , w[N];
    long long sum[M] , lv[M] , rv[M] , tv[M];
    inline void pushup(int x)
    {
    	int l = x << 1 , r = x << 1 | 1;
    	sum[x] = sum[l] + sum[r];
    	lv[x] = max(lv[l] , sum[l] + lv[r]);
    	rv[x] = max(rv[r] , sum[r] + rv[l]);
    	tv[x] = max(rv[l] + lv[r] , max(tv[l] , tv[r]));
    }
    void update(int p , int a , int l , int r , int x)
    {
    	if(l == r)
    	{
    		sum[x] = a , lv[x] = rv[x] = tv[x] = max(a , 0);
    		return;
    	}
    	int mid = (l + r) >> 1;
    	if(p <= mid) update(p , a , l , mid , x << 1);
    	else update(p , a , mid + 1 , r , x << 1 | 1);
    	pushup(x);
    }
    int main()
    {
    	int n , m , i;
    	long long ans = 0;
    	scanf("%d%d" , &n , &m);
    	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &v[i]);
    	for(i = 1 ; i <= m ; i ++ ) scanf("%d" , &w[i]);
    	for(i = 1 ; i <= n ; i ++ )
    	{
    		last[i] = pos[v[i]] , pos[v[i]] = i;
    		update(i , w[v[i]] , 1 , n , 1);
    		if(last[i])
    		{
    			update(last[i] , -w[v[i]] , 1 , n , 1);
    			if(last[last[i]]) update(last[last[i]] , 0 , 1 , n , 1);
    		}
    		ans = max(ans , tv[1]);
    	}
    	printf("%lld
    " , ans);
    	return 0;
    }
    

     

  • 相关阅读:
    Poj3126
    Poj1426
    2806 红与黑
    3100 蜗牛
    1225 八数码难题
    2549 自然数和分解
    2547 东方辉针城
    2928 你缺什么
    1629 01迷宫
    1029 遍历问题
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7573152.html
Copyright © 2011-2022 走看看