zoukankan      html  css  js  c++  java
  • Solution -「ROI 2019」「LOJ #3192」课桌

    (mathcal{Description})

      Link.

      原题意足够简洁啦。(

    (mathcal{Solution})

      乍一看比较棘手,但可以从座位的安排方式入手,有结论:

      一个班的学生按身高排序后,相邻的两两坐在一桌。

      证明略,比较显。

      第二个结论:

      设按上述方案分桌,从左至右将每桌编号为 (1sim n)。则每个班级的第 (i) 号桌都坐在同一个位子。

      考虑交换两桌不能使答案变优即证。

      考试的时候结论都看出来了结果写假了你敢信 qwq。

      再来考虑桌子,如果一张桌子的区间被另一桌子的区间覆盖,则这张桌子一定不需要。所以剩下的区间按左端点升序排列后,右端点亦为升序。则若第 (i_1) 桌选用 (j_1) 号桌子,第 (i_2) 桌选用 (j_2) 号桌子,就会有 (i_1<i_2Leftrightarrow j_1le j_2) 成立。所以直接决策单调性分治优化求解即可。复杂度 (mathcal O(nm+klog klog n))

    (mathcal{Code})

    /* Clearink */
    
    #include <cstdio>
    #include <vector>
    #include <cassert>
    #include <algorithm>
    
    #define rep( i, l, r ) for ( int i = l, repEnd##i = r; i <= repEnd##i; ++i )
    #define per( i, r, l ) for ( int i = r, repEnd##i = l; i >= repEnd##i; --i )
    
    typedef long long LL;
    typedef std::pair<int, int> PII;
    #define fi first
    #define se second
    
    inline int rint() {
    	int x = 0, s = getchar();
    	for ( ; s < '0' || '9' < s; s = getchar() );
    	for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
    	return x;
    }
    
    const int MAXN = 2e5;
    int n, m, c, h[MAXN * 2 + 5];
    LL pre[MAXN * 2 + 5], suf[MAXN * 2 + 5];
    PII desk[MAXN + 5];
    std::vector<int> group[MAXN + 5];
    
    inline LL solve( const int gl, const int gr, const int dl, const int dr ) {
    	if ( gl > gr ) return 0;
    	int gm = gl + gr >> 1, dm = -1, sz = ( m << 1 ) - 1;
    	std::vector<int>& curG = group[gm];
    	std::sort( curG.begin(), curG.end() );
    	rep ( i, 0, sz ) pre[i] = ( i ? pre[i - 1] : 0 ) + curG[i];
    	per ( i, sz, 0 ) suf[i] = suf[i + 1] + curG[i];
    	LL res = 1ll << 60;
    	rep ( i, dl, dr ) {
    		int l = desk[i].fi, r = desk[i].se;
    		int cl = std::lower_bound( curG.begin(),
    			curG.end(), l ) - curG.begin();
    		int cr = std::upper_bound( curG.begin(),
    	 		curG.end(), r ) - curG.begin() - 1;
    		LL cost = 1ll * l * cl - ( cl ? pre[cl - 1] : 0 )
    			+ suf[cr + 1] - 1ll * r * ( sz - cr );
    		if ( cost < res ) res = cost, dm = i;
    	}
    	return res + solve( gl, gm - 1, dl, dm ) + solve( gm + 1, gr, dm, dr );
    }
    
    int main() {
    	// freopen( "desk.in", "r", stdin );
    	// freopen( "desk.out", "w", stdout );
    	m = rint(), n = rint(), c = rint();
    	rep ( i, 1, c ) desk[i].fi = rint(), desk[i].se = rint();
    	std::sort( desk + 1, desk + c + 1 );
    	int idx = 0;
    	rep ( i, 1, c ) {
    		desk[idx += desk[i].fi != desk[i - 1].fi] = desk[i];
    	}
    	c = idx;
    	rep ( i, 1, m ) {
    		rep ( j, 1, n << 1 ) h[j] = rint();
    		std::sort( h + 1, h + ( n << 1 | 1 ) );
    		rep ( j, 1, n << 1 ) group[j + 1 >> 1].push_back( h[j] );
    	}
    	printf( "%lld
    ", solve( 1, n, 1, c ) );
    	return 0;
    }
    
    
  • 相关阅读:
    Linux基础命令:crontab
    linux基础命令:su和sudo
    Linux基础知识:文件权限管理以及umask
    Linux基础命令:useradd和groupadd
    Linux基础命令:more和less
    Linux基础命令:ln
    Linux基础命令:chattr和lsattr
    Linux基础命令:who和w
    vue项目1-pizza点餐系统6-路由精讲之复用router-view
    vue项目1-pizza点餐系统5-全局守卫
  • 原文地址:https://www.cnblogs.com/rainybunny/p/14413198.html
Copyright © 2011-2022 走看看