• [CF631E]Product Sum


    题目

    点这里看题目。

    分析

    设未交换时的结果为 (c) ,记 (s) 为前缀和数组。

    那么考虑将 (i) 交换到 (j) 之后( (j<i) ),交换的变化量为:

    [egin{aligned} &Delta=(s_i-s_j-A_i)+(j+1-i)A_i\ Rightarrow &Delta=(jA_i-s_j)+(s_i-iA_i) end{aligned} ]

    可以发现前面的括号内是关于 (j)(i) 的函数,且不看 (A_i) 则是 (j) 的一次函数。

    因此我们可以使用李超线段树维护 (0sim i-1) 的这些一次函数。当然,由于斜率单调,这里可以使用单调栈维护下凸包。

    反过来 (j>i) 的情况是类似的,化简的结果为:

    [Delta=(jA_i+s_j)+(-s_i-iA_i) ]

    类似维护即可。时间是 (O(nlog_2n))

    代码

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int MAXN = 2e5 + 5;
    
    template<typename _T>
    void read( _T &x )
    {
    	x = 0; char s = getchar(); int f = 1;
    	while( s < '0' || '9' < s ) { f = 1; if( s == '-' ) f = -1; s = getchar(); }
    	while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar(); }
    	x *= f;
    }
    
    template<typename _T>
    void write( _T x )
    {
    	if( x < 0 ) putchar( '-' ), x = -x;
    	if( 9 < x ) write( x / 10 );
    	putchar( x % 10 + '0' );
    }
    
    template<typename _T>
    _T MAX( const _T a, const _T b )
    {
    	return a > b ? a : b;
    }
    
    template<typename _T>
    void swapp( _T &x, _T &y )
    {
    	_T t = x; x = y, y = t;
    }
    
    struct Linear
    {
    	LL k, b;
    	Linear() { k = b = 0; }
    	Linear( LL K, LL B ) { k = K, b = B; }
    	LL operator () ( const LL x ) const { return k * x + b; }
    };
    
    Linear f[MAXN], func[MAXN];
    
    LL su[MAXN], val[MAXN];
    int A[MAXN], pos[MAXN], coe[MAXN];
    int N, tot;
    
    void Build( const int l, const int r )
    {
    	if( l > r ) return ; 
    	int mid = l + r >> 1;
    	f[mid] = Linear( 0, -INF );
    	Build( l, mid - 1 );
    	Build( mid + 1, r );
    }
    
    void Update( const int l, const int r, Linear nw )
    {
    	if( l > r ) return ;
    	int mid = l + r >> 1;
    	if( f[mid]( val[mid] ) < nw( val[mid] ) ) swapp( f[mid], nw );
    	if( f[mid]( val[l] ) <= nw( val[l] ) ) Update( l, mid - 1, nw );
    	else Update( mid + 1, r, nw );
    }
    
    LL Query( const int l, const int r, const int p )
    {
    	if( l > r ) return -INF;
    	int mid = l + r >> 1; LL ret = f[mid]( val[p] );
    	if( p < mid ) ret = MAX( Query( l, mid - 1, p ), ret );
    	if( mid < p ) ret = MAX( Query( mid + 1, r, p ), ret );
    	return ret;
    }
    
    void Discrete()
    {
    	tot = 0; for( int i = 1 ; i <= N ; i ++ ) val[++ tot] = A[i];
    	sort( val + 1, val + 1 + tot ); tot = unique( val + 1, val + 1 + tot ) - val - 1;
    	for( int i = 1 ; i <= N ; i ++ ) pos[i] = lower_bound( val + 1, val + 1 + tot, A[i] ) - val;
    }
    
    int main()
    {
    	read( N ); LL ans = 0, base = 0;
    	for( int i = 1 ; i <= N ; i ++ ) read( A[i] ), coe[i] = i, base += 1ll * i * A[i];
    	
    	Discrete(), Build( 1, tot ), func[0] = Linear( 0, 0 ), Update( 1, tot, func[0] );
    	for( int i = 1 ; i <= N ; i ++ ) func[i] = Linear( i, - ( su[i] = su[i - 1] + A[i] ) );
    	for( int i = 1 ; i <= N ; i ++ ) ans = MAX( ans, Query( 1, tot, pos[i] ) + su[i] - 1ll * i * A[i] ), Update( 1, tot, func[i] );
    	Build( 1, tot ), func[N + 1] = Linear( N + 1, 0 ), Update( 1, tot, func[N + 1] );
    	for( int i = N ; i ; i -- ) func[i] = Linear( i, su[i] = su[i + 1] + A[i] );
    	for( int i = N ; i ; i -- ) ans = MAX( ans, Query( 1, tot, pos[i] ) - su[i] - 1ll * i * A[i] ), Update( 1, tot, func[i] );
    	
    	write( ans + base ), putchar( '
    ' );
    	return 0;
    }
    
  • 相关阅读:
    如何在Web项目中给没有添加API核心组件添加APIController的帮助页HelpPage
    如何在MVC_WebAPI项目中的APIController帮助页面添加Web测试工具测试
    exception throw in progress runner thread_VS2015中SVN源代码无说明提交异常
    [转]AMBA、AHB、APB、ASB总线简介
    UML和模式应用4:初始阶段(6)--迭代方法中如何使用用例
    UML和模式应用4:初始阶段(5)--用例编写的准则
    startup_MK64F12.s文件解析
    [转] bss段、data段、text段
    [转]GDB-----2.watchpoint
    [转]GDB-----1.GDB概述
  • 原文地址:https://www.cnblogs.com/crashed/p/14157117.html
Copyright © 2020-2023  润新知