• 「Gym102979」Junkyeom's Contest


    题目

    点这里看题目。

    分析

    不难看出,对 (A) 排序后,(P_3,P_4,dots,P_7) 在序列上一定是连续的。因此实际上需要枚举的只有 (P_1,P_2,P_3) 三个数。

    我们需要做下决定:设 (q=P_4+P_5+P_6+P_7-P_3),则有 (P_1<P_2+P_3)(P_2<q) 两条限制。如果我们枚举 (P_1) 或者 (P_3),限制会集中在一侧,在一侧上要选出条件牵连的两个数来,难度颇大;而如果我们枚举 (P_2),这两条限制分居两侧,从每侧选出一个数,简单不少。因此,我们会选择枚举 (P_2)

    枚举好 (P_2) 后,我们需要求的是满足 (P_2<q)最大(P_3)。但注意到,如果有 (P_3le P_3'),且 (q<q'),那么 (P_3) 一定是不优于 (P_3')。因此我们可以扫描 (P_2),使用单调栈维护合法的 (P_3),查询二分。最大化 (P_3) 之后,(P_1) 也可以直接二分。

    因此,我们得到了 (O(nlog n)) 的算法。

    小结:

    1. 审慎地决定思考的方向,对于问题的分析不应停留于找出性质、获得解法 等等,分析也应该可以为你导出合理的思考方向
    2. 注意 (P_3) 待选点隐藏的单调性,类似的有「CSP-S2019」划分一题。

    代码

    #include <bits/stdc++.h>
    
    #define rep( i, a, b ) for( int i = (a) ; i <= (b) ; i ++ )
    #define per( i, a, b ) for( int i = (a) ; i >= (b) ; i -- )
    
    typedef long long LL;
    
    const int MAXN = 5e5 + 5;
    
    template<typename _T>
    void read( _T &x )/*{{{*/
    {
    	x = 0; char s = getchar(); int f = 1;
    	while( ! ( '0' <= s && s <= '9' ) ) { 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' );
    }/*}}}*/
    
    int stk[MAXN], top;
    
    LL P[MAXN], pre[MAXN], coe[MAXN];
    int N;
    
    int main()
    {
    	read( N );
    	rep( i, 1, N ) read( P[i] );
    	std :: sort( P + 1, P + 1 + N );
    	rep( i, 1, N ) pre[i] = pre[i - 1] + P[i];
    	LL ans = -1;
    	rep( i, 5, N )
    	{
    		if( top && coe[stk[1]] > P[i] )
    		{
    			int l = 1, r = top, mid;
    			while( l < r )
    			{
    				mid = ( l + r + 1 ) >> 1;
    				if( coe[stk[mid]] > P[i] ) l = mid;
    				else r = mid - 1;
    			}
    			int p = std :: lower_bound( P + 1, P + 1 + N, P[stk[l]] + P[i] ) - P - 1;
    			if( i < p && p <= N ) ans = std :: max( ans, coe[stk[l]] + 2 * P[stk[l]] + P[i] + P[p] );
    		}
    		coe[i] = pre[i - 1] - pre[i - 5] - P[i];
    		while( top && coe[stk[top]] <= coe[i] ) top --;
    		stk[++ top] = i;
    	}
    	write( ans ), putchar( '
    ' );
    	return 0;
    }
    
  • 相关阅读:
    How To Write A Business Plan 如何撰写商业计划书 笔记
    从“蚁族”现象看高等教育公平
    C# POS机客显
    node vscode 调试
    项目已被 macOS 使用,不能打开」的处理办法
    《BERT模型的优化改进方法》读书笔记
    面试突击50:单例模式有几种写法?
    面试突击51:为什么单例一定要加 volatile?
    Spring Cloud OpenFeign 的 5 个优化小技巧!
    WebSocket(SuperSocket.WebSocket实现)服务端主动断开客户端的连接
  • 原文地址:https://www.cnblogs.com/crashed/p/15192330.html
Copyright © 2020-2023  润新知