zoukankan      html  css  js  c++  java
  • Wannafly挑战赛2 C.Butterfly(线段树优化枚举)

    题目链接  C.Butterfly

    令$fd[i][j]$为以$s[i][j]$为起点开始往下走最大连续的‘X’个数

    令$fl[i][j]$为以$s[i][j]$为起点开始往左下走最大连续的‘X’个数

    令$fr[i][j]$为以$s[i][j]$为起点开始往左下走最大连续的‘X’个数

    令$a[i][j] = min(fd[i][j], fl[i][j])$, $b[i][j] = min(fd[i][j], fr[i][j])$

    对于每一个$(i, j)$, 我们要找到$(i, k)$

    使得$k$最大,并且$k >= j$, $k - j + 1 <= min(a[i][j], b[i][k])$

    $k - j + 1$必须为奇数

    把所有条件整理出来就是

    $k - j + 1 <= a[i][j]$

    $k - j + 1 <= b[i][k]$

    移项得到

    $k <= a[i][j] + j - 1$

    $k - b[i][k] + 1 <= j$

    所以我们可以对$k - b[i][k] + 1$排序,当$j$从$1$扫到$m$的时候每一次确保所有满足$k - b[i][k] + 1$的$k$都已经被添加到线段树中

    那么我们在$[j, a[i][j] + j - 1]$这段区间里面查找最大值(也就是符合条件的最大的$k$)更新答案即可。

    注意分奇偶讨论

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define	fi		first
    #define	se		second
    #define	MP		make_pair
    #define lson		i << 1, L, mid
    #define rson		i << 1 | 1, mid + 1, R
    
    typedef pair <int, int> PII;
    
    const int N = 2010;
    
    char s[N][N];
    int  fd[N][N], fl[N][N], fr[N][N], a[N][N], b[N][N];
    int  n, m, now;
    int  t[N << 4];
    int  cnt, mx, ans = 0;
    
    PII  c[N];
    
    inline void pushup(int i){ t[i] = max(t[i << 1], t[i << 1 | 1]); }
    
    void update(int i, int L, int R, int x, int val){
    	if (L == R && L == x){
    		t[i] = max(t[i], val);
    		return;
    	}
    
    	int mid = (L + R) >> 1;
    	if (x <= mid) update(lson, x, val);
    	else update(rson, x, val);
    	pushup(i);
    }
    
    int query(int i, int L, int R, int l, int r){
    	if (l <= L && R <= r) return t[i];
    	int mid = (L + R) >> 1;
    	if (r <= mid) return query(lson, l, r);
    	else if (l > mid) return query(rson, l, r);
    	else return max(query(lson, l, r), query(rson, l, r));
    }
    
    int main(){
    
    	scanf("%d%d", &n, &m);
    	rep(i, 1, n) scanf("%s", s[i] + 1);
    	dec(i, n, 1) rep(j, 1, m){
    		fd[i][j] = s[i][j] == 'X' ? fd[i + 1][j] + 1 : 0;
    		fl[i][j] = s[i][j] == 'X' ? fl[i + 1][j - 1] + 1 : 0;
    		fr[i][j] = s[i][j] == 'X' ? fr[i + 1][j + 1] + 1 : 0;
    	}
    
    	rep(i, 1, n) rep(j, 1, m) a[i][j] = min(fd[i][j], fr[i][j]), b[i][j] = min(fd[i][j], fl[i][j]);
    
    	mx  = m << 1;
    	ans = 0;
    
    	rep(i, 1, n){
    		cnt = 0;
    		for (int j = 1; j <= m; j += 2) if (b[i][j]) c[++cnt] = MP(j - b[i][j] + 1, j);
    		sort(c + 1, c + cnt + 1);
    
    		memset(t, 0, sizeof t);
    		now = 0;
    		for (int j = 1; j <= m; j += 2){
    			if (!a[i][j]) continue;
    			while (now < cnt){
    				if (c[now + 1].fi <= j){
    					++now;
    					update(1, 1, mx, c[now].se, c[now].se);
    					if (now >= cnt) break;
    				}
    				else break;
    			}
    
    			int et = query(1, 1, mx, j, a[i][j] + j - 1);
    			ans = max(ans, et - j + 1);
    		}
    
    		cnt = 0;
    		for (int j = 2; j <= m; j += 2) if (b[i][j]) c[++cnt] = MP(j - b[i][j] + 1, j);
    		sort(c + 1, c + cnt + 1);
    
    		memset(t, 0, sizeof t);
    		now = 0;
    		for (int j = 2; j <= m; j += 2){
    			if (!a[i][j]) continue;
    			while (now < cnt){
    				if (c[now + 1].fi <= j){
    					++now;
    					update(1, 1, mx, c[now].se, c[now].se);
    					if (now >= cnt) break;
    				}
    				else break;
    			}
    
    			int et = query(1, 1, mx, j, a[i][j] + j - 1);
    			ans = max(ans, et - j + 1);
    		}
    	}
    
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

  • 相关阅读:
    GridView中使用DataFromatString
    添加文件Node
    GridView技巧1:加入序号
    Android UI控件Spinner控件的学习
    Android UI开发之RadioButton
    二叉树
    visual studio toolbox 修复
    github笔记
    nhibernate manytoone 没有匹配项时的异常
    DataMember 特性
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7953671.html
Copyright © 2011-2022 走看看