• 「雅礼集训 2018 Day10」贪玩蓝月


    题目

    点这里看题目。

    分析

    离线的话,我们显然可以 线段树分治 + DP ,时间复杂度大概是 (O(mlog_2m+mp))

    不过,既然题目明确要求在线,却还不开强制在线,我们就应该去思考一下在线算法。

    显然我们需要一个 DP 去维护答案,这里不再赘述。

    考虑我们直接处理的难点之一是双端队列两段可操作,而一端可操作的结构,栈,就可以简单地维护 DP 。因此,我们考虑将双端队列拆成两栈分别维护左端和右端

    有了这个思路,剩下的都比较简单了。插入操作可以直接维护 DP 数组。删除操作可以把栈顶的 DP 数组清空。查询的时候,我们枚举一端的 DP 值 (dpl(i)) ,此时对应可用的 (dpr) 的值必然是一段区间,我们可以考虑使用单调队列之类的数据结构维护一下。

    插入、查询都可以做到 (O(p)) 。删除时,如果一端的栈已经被删空了,我们需要在另一端的栈里打上标记,在之后对两个栈进行均分重构

    时间复杂度是 ...... (O(? imes p))

    代码

    #include <cstdio>
    #include <cstring>
    
    typedef long long LL;
    
    const LL INF = 1e10;
    const int MAXN = 5e4 + 5, MAXP = 505;
    
    template<typename _T>
    void read( _T &x )
    {
    	x = 0;char s = getchar();int f = 1;
    	while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
    	while( s >= '0' && 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 ) + 1; }
    	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;
    }
    
    LL DPL[MAXN][MAXP], DPR[MAXN][MAXP];
    
    LL f[MAXP << 1];
    int q[MAXP];
    
    int stkL[MAXN], stkR[MAXN];
    int tmp[MAXN];
    
    int w[MAXN], v[MAXN];
    int N, P, topL, topR, butL, butR;
    
    void rebuild();
    void upt( LL &x, const LL v ) { x = MAX( x, v ); }
    int fix( const int a ) { return ( a % P + P ) % P; }
    
    void popL() 
    { 
    	if( ! topL ) { butR ++; return ; }
    	topL --; 
    	if( ! topL ) rebuild(); 
    }
    
    void popR() 
    { 
    	if( ! topR ) { butL ++; return ; }
    	topR --; 
    	if( ! topR ) rebuild(); 
    }
    
    void insertL( const int id )
    {
    	w[id] %= P, stkL[++ topL] = id;
    	for( int i = 0 ; i < P ; i ++ ) DPL[topL][i] = -INF;
    	for( int i = 0 ; i < P ; i ++ ) 
    		upt( DPL[topL][i], DPL[topL - 1][i] ),
    		upt( DPL[topL][( i + w[id] ) % P], DPL[topL - 1][i] + v[id] );
    }
    
    void insertR( const int id )
    {
    	w[id] %= P, stkR[++ topR] = id;
    	for( int i = 0 ; i < P ; i ++ ) DPR[topR][i] = -INF;
    	for( int i = 0 ; i < P ; i ++ ) 
    		upt( DPR[topR][i], DPR[topR - 1][i] ),
    		upt( DPR[topR][( i + w[id] ) % P], DPR[topR - 1][i] + v[id] );	
    }
    
    void rebuild()
    {
    	int siz = 0;
    	for( int i = topL ; i > butL ; i -- ) tmp[++ siz] = stkL[topL];
    	for( int i = butR + 1 ; i <= topR ; i ++ ) tmp[++ siz] = stkR[i];
    	butL = butR = topL = topR = 0; 
    	int mid = siz >> 1;
    	for( int i = mid ; i ; i -- ) insertL( tmp[i] );
    	for( int i = mid + 1 ; i <= siz ; i ++ ) insertR( tmp[i] ); 
    }
    
    LL query()
    {
    	if( butL || butR ) rebuild();
    	int L, R;
    	LL ans = -INF;
    	int h = 1, t = 0, r = 0;
    	read( L ), read( R );
    	for( int i = 0 ; i < P ; i ++ ) f[i] = f[i + P] = DPR[topR][i];
    	for( int i = L ; ~ i ; i -- )
    	{
    		for( ; r <= fix( R - i ) ; r ++ )
    		{
    			while( h <= t && f[q[t]] <= f[r] ) t --;
    			q[++ t] = r;
    		}
    		while( h <= t && q[h] < L - i ) h ++;
    		ans = MAX( ans, f[q[h]] + DPL[topL][i] );
    	}
    	r = 0;
    	for( int i = P - 1 ; i > L ; i -- )
    	{
    		for( ; r <= R - i + P ; r ++ )
    		{
    			while( h <= t && f[q[t]] <= f[r] ) t --;
    			q[++ t] = r;
    		}
    		while( h <= t && q[h] < L - i + P ) h ++;
    		ans = MAX( ans, f[q[h]] + DPL[topL][i] );
    		
    	}
    	return ans < 0 ? -1 : ans;
    }
    
    int main()
    {
    	int qwq;
    	read( qwq );	
    	char op[10];
    	read( N ), read( P );
    	for( int i = 1 ; i < P ; i ++ )
    		DPL[0][i] = DPR[0][i] = -INF;
    	for( int cas = 1 ; cas <= N ; cas ++ )
    	{
    		scanf( "%s", op );
    		if( ! strcmp( op, "IF" ) ) read( w[cas] ), read( v[cas] ), 
    		insertL( cas ); 
    		if( ! strcmp( op, "IG" ) ) read( w[cas] ), read( v[cas] ), 
    		insertR( cas );
    		if( ! strcmp( op, "DF" ) ) popL();
    		if( ! strcmp( op, "DG" ) ) popR();
    		if( ! strcmp( op, "QU" ) ) write( query() ), putchar( '
    ' );
    	}
    	return 0;
    }
    
  • 相关阅读:
    win7桌面的文件路径是否可以更改
    win10怎么更新flash到最新版本【系统天地】
    centos7 lnmp环境部署
    thinkphp5 部署注意事项
    linux下导入、导出mysql数据库命令的实现方法
    Centos7 系统下怎么更改apache默认网站目录
    centos7 配置lamp 环境
    Redis笔记(4)独立功能的实现
    Redis笔记(3)多数据库实现
    Redis笔记(2)单机数据库实现
  • 原文地址:https://www.cnblogs.com/crashed/p/13463354.html
Copyright © 2020-2023  润新知