zoukankan      html  css  js  c++  java
  • [AGC023D] Go Home

    题目

    点这里看题目。

    分析

    一眼望过去似乎就是每个人往自己的家的方向投?

    幸好出题人够良心,光是样例 1 就帮你把这个错误的想法叉掉了

    每个人往自己家投,前提条件是自己的票可以让自己尽早回家

    比如,(n) 楼居民如果盲目向右跟风,那么很有可能投着投着,还没回到家,就因为投右的人都走得差不多了,结果反被拉着向左走,回家的时间反而变晚了。

    又考虑到最后到家的人要么是第 1 幢楼的人,要么是第 (n) 幢楼的人。如果有 (p_1ge p_n),那么在某次投票中,(n) 楼居民一定会被迫跟着 1 楼居民走;而显然 1 楼居民不到家,他们就到不了家,因此他们一定会全力支持 1 楼居民提早回家。考虑到 (n) 楼居民的策略现在一定和 1 楼居民的策略基本一致,我们可以看作是将 (n) 楼居民搬迁到了 1 楼,最后再搬回 (n) 楼。

    相似的,当 (p_1< p_n) 的时候,一定是 1 楼居民全力支持 (n) 楼居民,而 (n) 楼居民可能最后可以夺取掌控权,暂时还无法论断。

    那么,进行“搬迁”操作后我们得到了相似的子问题,可以递归解决,时间为 (O(n))

    得出结论,人多才是硬道理

    小结:

    1. 分析多个对象的问题,可以抓住关键的几个对象来分析他们的策略;
    2. 相似问题、递归思想;
    3. 其中“将 (n) 楼居民搬迁到 1 楼”,这个想法很有趣;

    代码

    #include <set>
    #include <cstdio>
    using namespace std;
    
    #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 = 1e5 + 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 ABS( const _T a )
    {
    	return a < 0 ? -a : a;
    }
    
    LL X[MAXN], P[MAXN];
    int N, S; LL ans = 0;
    
    int Solve( const int l, const int r )
    {
    	if( S <= X[l] ) return ans += X[r] - S, X[r];
    	if( S >= X[r] ) return ans += S - X[l], X[l];
    	if( P[l] >= P[r] )
    	{
    		P[l] += P[r];
    		int t = Solve( l, r - 1 );
    		ans += X[r] - t;
    		return X[r];
    	}
    	else
    	{
    		P[r] += P[l];
    		int t = Solve( l + 1, r );
    		ans += t - X[l];
    		return X[l];
    	}
    }
    
    int main()
    {
    	read( N ), read( S );
    	rep( i, 1, N ) 
    		read( X[i] ), read( P[i] );
    	Solve( 1, N );
    	write( ans ), putchar( '
    ' );
    	return 0;
    }
    
  • 相关阅读:
    Python的历史
    python excel
    excel xdr wdr
    sql 常用命令
    selenium 配置firefox
    SQL 一直恢复状态解决方法
    sqlserver 学习
    ITCHAT用法
    健身卡属性,以及业务规则,
    安装REDIS
  • 原文地址:https://www.cnblogs.com/crashed/p/14952235.html
Copyright © 2011-2022 走看看