zoukankan      html  css  js  c++  java
  • 【题解】Pirate Chest World Finals 2013 笛卡尔树

    我觉得这个题挺水的。。不过当年似乎没过多少人,而且我居然到了最后1h才会做。。感觉水平倒退了。
    大体思路是“枚举宝箱的长、宽、底面深度,就可以直接算出高”
    枚举宝箱所在的上边界和下边界,中间取最浅深度拍扁成一维
    然后直接做笛卡尔树就行了

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int N = 510;
    int _w;
    
    int a, b, n, m, d[N][N];
    ll ans;
    
    int h[N];
    int lc[N], rc[N], lb[N], rb[N], stk[N], top, rt;
    
    void build() {
    	top = 0;
    	memset(lc, 0, sizeof lc);
    	memset(rc, 0, sizeof rc);
    	stk[top++] = 1;
    	for( int i = 2; i <= m; ++i ) {
    		while( top && h[i] < h[stk[top-1]] ) {
    			lc[i] = stk[top-1];
    			--top;
    		}
    		if( top ) rc[stk[top-1]] = i;
    		stk[top++] = i;
    	}
    	rt = stk[0];
    }
    
    void update( int x, int y, int dep ) {
    	// printf( "update(%d, %d, %d)
    ", x, y, dep );
    	int area = x * y;
    	int pond = n * m;
    	ll height = 1LL * dep * pond / (pond - area);
    	if( 1LL * dep * pond % (pond - area) == 0 )
    		--height;
    	ans = max( ans, height * area );
    }
    
    void dfs( int u, int len ) {
    	lb[u] = rb[u] = u;
    	if( lc[u] ) {
    		dfs( lc[u], len );
    		lb[u] = lb[lc[u]];
    	}
    	if( rc[u] ) {
    		dfs( rc[u], len );
    		rb[u] = rb[rc[u]];
    	}
    	int width = rb[u] - lb[u] + 1;
    	if( len <= a ) width = min(width, b);
    	else width = min(width, a);
    	int dep = h[u];
    	update(len, width, dep);
    }
    
    void _solve( int len ) {
    	build();
    	dfs(rt, len);
    }
    
    void solve() {
    	for( int up = 1; up <= n; ++up ) {
    		for( int j = 1; j <= m; ++j )
    			h[j] = d[up][j];
    		for( int down = up; down <= n; ++down ) {
    			int len = down - up + 1;
    			if( len > b ) break;
    			for( int j = 1; j <= m; ++j ) {
    				h[j] = min( h[j], d[down][j] );
    			}
    			_solve(len);
    		}
    	}
    }
    
    int main() {
    	_w = scanf( "%d%d%d%d", &a, &b, &n, &m );
    	if( a > b ) swap(a, b);
    	for( int i = 1; i <= n; ++i )
    		for( int j = 1; j <= m; ++j )
    			_w = scanf( "%d", &d[i][j] );
    	solve();
    	printf( "%lld
    ", ans );
    	return 0;
    }
    
  • 相关阅读:
    用vs调试sql存储过程
    Html插入Flash.object.embed.swf各个参数值详解介绍[等比例缩放]
    SQL SERVER分区具体例子详解
    C#身份证识别相关技术
    C#调用Java方法(详细实例)
    Visual Studio各版本工程文件之间的转换
    彻底解决asp.net mvc5.2.2:vs2013 cshtml视图文件报错(当前上下文中不存在名称“model”,ViewBag,Url)
    HTML 5 Web 本地存储
    让WeuiPicker隐藏日期中的日,只保留年月
    javascript获取值
  • 原文地址:https://www.cnblogs.com/mlystdcall/p/12497892.html
Copyright © 2011-2022 走看看