zoukankan      html  css  js  c++  java
  • Solution-「ARC 063D」「AT 2149」Snuke's Coloring 2

    (mathcal{Decription})

      Link.

      平面上有一个左下角坐标 ((0,0)) 右上角坐标 ((W,H)) 的矩形,起初长方形内部被涂白。

    现在给定 (n) 个点,你每次在以下 (4) 种操作中选择一种:

    • 将矩形内 (x<x_i) 的区域涂黑;
    • 将矩形内 (x>x_i) 的区域涂黑;
    • 将矩形内 (y<y_i) 的区域涂黑;
    • 将矩形内 (y>y_i) 的区域涂黑。

      最大化操作后白色矩阵周长。

      (nle3 imes10^5)(W,Hle10^8)

    (mathcal{Solution})

      就挺 amazing 的题呐。

      题意等价于求周长最大的矩形,使得矩形内不包含任意一个点。

      首先,答案有下界 (2max{H,W}+2)。考虑一个周长超过该下界的矩形,它一定跨过 (y=frac{H}2)(x=frac{W}2),所以只需要分别求出跨过着两条直线的周长最大的合法矩形。下以跨过 (l:y=frac{H}2) 的情形为例。

      从左到右用一条扫描线,设当前 (x=x_0) 轴上高于 (l) 的最低点离 (l) 的距离为 (u),低于 (l) 的最高点离 (l) 的距离为 (d),那么当矩形过 (x=x_0) 时,高度 (le u+d)

      接下来,把从 (x_1)(x_2) 的横向宽度表达为 ((W-x_1)-(W-x_2)),然后线段树维护矩形左边界为 (x=x_0) 时,高度 (+(W-x_1)) 的值。用单调递减的单调栈维护 (u)(d),弹栈时修改一段区间的值,最后求前缀最大值即可。(建议参照代码理解。)

    (mathcal{Code})

    /* Clearink */
    
    #include <stack>
    #include <cstdio>
    #include <algorithm>
    
    inline int rint () {
    	int x = 0; char s = getchar ();
    	for ( ; s < '0' || '9' < s; s = getchar () );
    	for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
    	return x;
    }
    
    inline int min_ ( const int a, const int b ) { return a < b ? a : b; }
    inline int max_ ( const int a, const int b ) { return a < b ? b : a; }
    
    const int MAXN = 3e5;
    int n, W, H, x[MAXN + 5], up[MAXN + 5], dn[MAXN + 5];
    std::stack<int> stku, stkd;
    
    struct Point {
    	int x, y;
    	inline bool operator < ( const Point& p ) const { return x < p.x; }
    } p[MAXN + 5];
    
    struct SegmentTree {
    	int mx[MAXN << 2], tag[MAXN << 2];
    
    	inline void pushup ( const int rt ) {
    		mx[rt] = max_ ( mx[rt << 1], mx[rt << 1 | 1] );
    	}
    
    	inline void pushdn ( const int rt ) {
    		int& k = tag[rt];
    		if ( !k ) return ;
    		mx[rt << 1] += k, tag[rt << 1] += k;
    		mx[rt << 1 | 1] += k, tag[rt << 1 | 1] += k;
    		k = 0;
    	}
    
    	inline void clear ( const int rt, const int l, const int r ) {
    		mx[rt] = tag[rt] = 0;
    		if ( l == r ) return ;
    		int mid = l + r >> 1;
    		clear ( rt << 1, l, mid ), clear ( rt << 1 | 1, mid + 1, r );
    	}
    
    	inline void update ( const int rt, const int l, const int r,
    		const int ul, const int ur, const int uv ) {
    		if ( ul <= l && r <= ur ) return mx[rt] += uv, tag[rt] += uv, void ();
    		int mid = l + r >> 1; pushdn ( rt );
    		if ( ul <= mid ) update ( rt << 1, l, mid, ul, ur, uv );
    		if ( mid < ur ) update ( rt << 1 | 1, mid + 1, r, ul, ur, uv );
    		pushup ( rt );
    	}
    
    	inline int query ( const int rt, const int l, const int r,
    		const int ql, const int qr ) {
    		if ( ql <= l && r <= qr ) return mx[rt];
    		int mid = l + r >> 1, ret = 0; pushdn ( rt );
    		if ( ql <= mid ) ret = query ( rt << 1, l, mid, ql, qr );
    		if ( mid < qr ) ret = max_ ( ret, query ( rt << 1 | 1, mid + 1, r, ql, qr ) );
    		return ret;
    	}
    } segt;
    
    inline int solve ( const int n, const int W, const int H ) {
    	if ( !n ) return 0;
    	int mid = H >> 1, cnt = 0, ret = 0;
    	for ( ; !stku.empty (); stku.pop () );
    	for ( ; !stkd.empty (); stkd.pop () );
    	segt.clear ( 1, 1, n );
    	stku.push ( 0 ), stkd.push ( 0 );
    	for ( int i = 1; i <= n; ) {
    		x[++ cnt] = p[i].x;
    		up[cnt] = H - mid, dn[cnt] = mid;
    		for ( ; i <= n && p[i].x == x[cnt]; ++ i ) {
    			if ( p[i].y >= mid ) up[cnt] = min_ ( up[cnt], p[i].y - mid );
    			if ( p[i].y <= mid ) dn[cnt] = min_ ( dn[cnt], mid - p[i].y );
    		}
    		int las;
    		while ( up[las = stku.top ()] > up[cnt] ) {
    			stku.pop ();
    			segt.update ( 1, 1, n, stku.top () + 1, las, up[cnt] - up[las] );
    		}
    		stku.push ( cnt );
    		while ( dn[las = stkd.top ()] > dn[cnt] ) {
    			stkd.pop ();
    			segt.update ( 1, 1, n, stkd.top () + 1, las, dn[cnt] - dn[las] );
    		}
    		stkd.push ( cnt );
    		segt.update ( 1, 1, n, cnt, cnt, W - x[cnt - 1] + up[cnt] + dn[cnt] );
    		ret = max_ ( ret, segt.query ( 1, 1, n, 1, cnt ) - W + p[i].x );
    	}
    	return ret;
    }
    
    int main () {
    	W = rint (), H = rint (), n = rint ();
    	for ( int i = 1; i <= n; ++ i ) {
    		p[i].x = rint (), p[i].y = rint ();
    		if ( !p[i].x || p[i].x == W || !p[i].y || p[i].y == H ) -- i, -- n;
    	}
    	int ans = 0;
    	std::sort ( p + 1, p + n + 1 ), p[n + 1].x = W;
    	for ( int i = 1; i <= n + 1; ++ i ) {
    		ans = max_ ( ans, H + p[i].x - p[i - 1].x );
    	}
    	ans = max_ ( ans, solve ( n, W, H ) );
    	for ( int i = 1; i <= n; ++ i ) p[i].x ^= p[i].y ^= p[i].x ^= p[i].y;
    	std::sort ( p + 1, p + n + 1 ), p[n + 1].x = H;
    	for ( int i = 1; i <= n + 1; ++ i ) {
    		ans = max_ ( ans, W + p[i].x - p[i - 1].x );
    	}
    	ans = max_ ( ans, solve ( n, H, W ) );
    	printf ( "%d
    ", ans << 1 );
    	return 0;
    }
    
  • 相关阅读:
    pandas 数据结构基础与转换
    Python 基础常用
    css 横向滚动条webkit-scrollbar
    hive mysql 初始化
    hive 的理解
    hive 踩坑
    hbase 调试各种报错
    hbase shell常用命令
    mysql 性能测试工具 mysqlslap
    【CDH学习之一】CDH简介
  • 原文地址:https://www.cnblogs.com/rainybunny/p/13872475.html
Copyright © 2011-2022 走看看