题目链接  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\n", ans);
return 0;
}

  

Wannafly挑战赛2 C.Butterfly(线段树优化枚举)的更多相关文章

  1. [USACO2005][POJ3171]Cleaning Shifts(DP+线段树优化)

    题目:http://poj.org/problem?id=3171 题意:给你n个区间[a,b],每个区间都有一个费用c,要你用最小的费用覆盖区间[M,E] 分析:经典的区间覆盖问题,百度可以搜到这个 ...

  2. Weak Pair---hud5877大连网选(线段树优化+dfs)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5877  题意:给你一颗树,有n个节点,每个节点都有一个权值v[i]:现在求有多少对(u,v ...

  3. CodeForces 558E(计数排序+线段树优化)

    题意:一个长度为n的字符串(只包含26个小字母)有q次操作 对于每次操作 给一个区间 和k k为1把该区间的字符不降序排序 k为0把该区间的字符不升序排序 求q次操作后所得字符串 思路: 该题数据规模 ...

  4. HDU4719-Oh My Holy FFF(DP线段树优化)

    Oh My Holy FFF Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) T ...

  5. UOJ#77. A+B Problem [可持久化线段树优化建边 最小割]

    UOJ#77. A+B Problem 题意:自己看 接触过线段树优化建图后思路不难想,细节要处理好 乱建图无果后想到最小割 白色和黑色只能选一个,割掉一个就行了 之前选白色必须额外割掉一个p[i], ...

  6. Codeforces 558E A Simple Task (计数排序&&线段树优化)

    题目链接:http://codeforces.com/contest/558/problem/E E. A Simple Task time limit per test5 seconds memor ...

  7. 2019.03.09 codeforces833B. The Bakery(线段树优化dp)

    传送门 线段树优化dpdpdp入门题. 要求把nnn个数分成kkk段,每段价值为里面不相同的数的个数,求所有段的价值之和最大值.n≤35000,k≤50n\le35000,k\le50n≤35000, ...

  8. Codeforces 1045. A. Last chance(网络流 + 线段树优化建边)

    题意 给你 \(n\) 个武器,\(m\) 个敌人,问你最多消灭多少个敌人,并输出方案. 总共有三种武器. SQL 火箭 - 能消灭给你集合中的一个敌人 \(\sum |S| \le 100000\) ...

  9. bzoj千题计划311:bzoj5017: [Snoi2017]炸弹(线段树优化tarjan构图)

    https://www.lydsy.com/JudgeOnline/problem.php?id=5017 暴力: 对于每一个炸弹,枚举所有的炸弹,看它爆炸能不能引爆那个炸弹 如果能,由这个炸弹向引爆 ...

随机推荐

  1. python 监控日志

    #需求: #1.每分钟监控服务器日志,ip请求超过200次的,加入黑名单 #1.读文件,获取到每行的内容 open readlines # 178.210.90.90 - - [04/Jun/2017 ...

  2. GoF23种设计模式之结构型模式之外观模式

    一.概述         为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 二.适用性 1.当你要为一个复杂子系统提供一个简单接口的时候.子系统 ...

  3. T-SQL中的indexof函数

    在C#字符串中查找字符有indexof方法,那么在T-SQL与之相对应的是CHARINDEX方法,其语法为CHARINDEX(要查找的字符,字符串),返回一个数字. CHARINDEX(',','aa ...

  4. 九度oj 题目1380:lucky number

    题目描述: 每个人有自己的lucky number,小A也一样.不过他的lucky number定义不一样.他认为一个序列中某些数出现的次数为n的话,都是他的lucky number.但是,现在这个序 ...

  5. iOS开发中六种手势识别

    iOS开发中手势识别有六种: 轻击手势(TapGestureRecognizer), 轻扫手势 (SwipeGestureRecognizer), 长按手势(LongPressGestureRecog ...

  6. 【Luogu】P2657windy数(数位DP)

    题目链接 正式迈入了数位DP的大门…… 心情激动 (看我立个flag,我如果专攻数位DP的话,到wc之前就会有秒数位DP蓝题的能力) 数位DP讲解链接 讲的非常详细,良心博客.比我写的博客加在一起还要 ...

  7. NYOJ——301递推求值(矩阵快速幂)

    递推求值 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 给你一个递推公式: f(x)=a*f(x-2)+b*f(x-1)+c 并给你f(1),f(2)的值,请求出f(n)的 ...

  8. BZOJ 4817 [Sdoi2017]树点涂色 ——LCT 线段树

    同BZOJ3779. SDOI出原题,还是弱化版的. 吃枣药丸 #include <map> #include <cmath> #include <queue> # ...

  9. [luoguP2774] 方格取数问题(最大点权独立集)

    传送门 引入两个概念: 最小点权覆盖集:满足每一条边的两个端点至少选一个的最小权点集. 最大点权独立集:满足每一条边的两个端点最多选一个的最大权点集. 现在对网格染色,使得相邻两点颜色不同,之后把两个 ...

  10. Element 'plugin' cannot have character [children], because the type's content type is element-only

    原因是你复制的时候,带了一些特殊符号. 解决方案: 将那一串代码复制到notpad++ 或者文本上面,再复制到你的编译器里面,就可以解决问题了