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\n", ans);
- return 0;
- }
Wannafly挑战赛2 C.Butterfly(线段树优化枚举)的更多相关文章
- [USACO2005][POJ3171]Cleaning Shifts(DP+线段树优化)
题目:http://poj.org/problem?id=3171 题意:给你n个区间[a,b],每个区间都有一个费用c,要你用最小的费用覆盖区间[M,E] 分析:经典的区间覆盖问题,百度可以搜到这个 ...
- Weak Pair---hud5877大连网选(线段树优化+dfs)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5877 题意:给你一颗树,有n个节点,每个节点都有一个权值v[i]:现在求有多少对(u,v ...
- CodeForces 558E(计数排序+线段树优化)
题意:一个长度为n的字符串(只包含26个小字母)有q次操作 对于每次操作 给一个区间 和k k为1把该区间的字符不降序排序 k为0把该区间的字符不升序排序 求q次操作后所得字符串 思路: 该题数据规模 ...
- 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 ...
- UOJ#77. A+B Problem [可持久化线段树优化建边 最小割]
UOJ#77. A+B Problem 题意:自己看 接触过线段树优化建图后思路不难想,细节要处理好 乱建图无果后想到最小割 白色和黑色只能选一个,割掉一个就行了 之前选白色必须额外割掉一个p[i], ...
- Codeforces 558E A Simple Task (计数排序&&线段树优化)
题目链接:http://codeforces.com/contest/558/problem/E E. A Simple Task time limit per test5 seconds memor ...
- 2019.03.09 codeforces833B. The Bakery(线段树优化dp)
传送门 线段树优化dpdpdp入门题. 要求把nnn个数分成kkk段,每段价值为里面不相同的数的个数,求所有段的价值之和最大值.n≤35000,k≤50n\le35000,k\le50n≤35000, ...
- Codeforces 1045. A. Last chance(网络流 + 线段树优化建边)
题意 给你 \(n\) 个武器,\(m\) 个敌人,问你最多消灭多少个敌人,并输出方案. 总共有三种武器. SQL 火箭 - 能消灭给你集合中的一个敌人 \(\sum |S| \le 100000\) ...
- bzoj千题计划311:bzoj5017: [Snoi2017]炸弹(线段树优化tarjan构图)
https://www.lydsy.com/JudgeOnline/problem.php?id=5017 暴力: 对于每一个炸弹,枚举所有的炸弹,看它爆炸能不能引爆那个炸弹 如果能,由这个炸弹向引爆 ...
随机推荐
- java的一些相关介绍(2013-10-07-163 写的日志迁移
java是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台(即JavaSE, JavaEE, Jav ...
- jmeter接口测试 ——学习笔记
JMETER常用操作 1.jmeter做http脚本 Http请求页面内容介绍 添加cookie 线程组-添加-配置元件--HTTP Cookie管理器 添加权限验证 不能使用普通用户修改学生金币,接 ...
- linux系统装载ELF过程
参考:程序员的自我修养 fork -->execve() //----kenerl space--------------- sys_execve() /*arch\i386\kernel\pr ...
- 2015多校训练第二场 hdu5305
把这题想复杂了,一直在考虑怎么快速的判断将选的边和已选的边无冲突,后来经人提醒发现这根本没必要,反正数据也不大开两个数组爆搜就OK了,搜索之前要先排除两种没必要搜的情况,这很容易想到,爆搜的时候注意几 ...
- <node>……express的中间件……//
Express是一个基于Node.js平台的web应用开发框架,在Node.js基础之上扩展了web应用开发所需要的基础功能,从而使得我们开发Web应用更加方便.更加快捷. 中间件是什么? 中间件函数 ...
- Makefile基础(一)
在大型的C语言项目中,一般都是由多个源文件编译链接形成的可执行程序,而这些源文件的处理步骤,通常交给Makefile来管理,Makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后 ...
- python - work5 - 类与对象
# -*- coding:utf-8 -*- '''@project: jiaxy@author: Jimmy@file: work_20181119.py@ide: PyCharm Communit ...
- Python全栈开发第二期课表
day01-python 全栈开发-基础篇 01 开课介绍 01:55:13 ★ 02 开课介绍02 01:28:31 ★ 03 开课介绍03 00:22:55 ...
- html 标签附加文本属性
<!DOCTYPE html> <html> <head> <script> function showDetails(animal) { var an ...
- how can I ues Dataset to shuffle a large whole dataset?
The Dataset.shuffle() implementation is designed for data that could be shuffled in memory; we're co ...