原题传送门
如果可以,尽可能经过所有蹦床
只要到达一个蹦床,那么就能到达所有蹦床

暂且先不考虑高度相平的情况,那么必定形如

假设我现在正在aaa蹦床,我可以跳到ddd,再回到aaa
假设我现在正在bbb蹦床,我可以先跳到eee,再回到bbb,再跳到ccc,再回到bbb
假设我现在正在ccc蹦床,我什么也干不了
这样我就把蹦床的三种位置情况的操作方法搞清楚了

如果蹦床在一段斜坡中,可以跳到旁边的高峰,在回来(蹦床在顶峰的情况归于此)
如果蹦床在谷底处,可以分别往两边的高峰跳,再跳回来

然后讨论起点

如果起点,能跑到蹦床,就跑向蹦床
因为,只要到达了蹦床,就可以蹦床连击了

但是如果起点到不了蹦床,那就只能往两边看看,能走多远

我需要处理出,每个点,往左、往右,一直上山、下山能走多远
然后用线段树维护,对于每个蹦床,从它旁边的高峰跑到它的这一段点区间覆盖1,表示我走过了

都做好之后,我现在站在最后一个蹦床,可以跳向某一个高峰,再往某一个方向跑到最低处

蓝线是已经覆盖的,每条绿线减去蓝线中取最大值,这部分是线段树的用处

最后,如果有高度相同的怎么办,可以多开个数组存储一下
这个思路非常暴力,谨慎参考

Code:

#include <bits/stdc++.h>
#define maxn 300010
#define ls rt << 1
#define rs rt << 1 | 1
using namespace std;
int n, st, a[maxn], b[maxn], cnt[maxn], peakl[maxn], peakr[maxn], bottoml[maxn], bottomr[maxn], samel[maxn], samer[maxn];
int tag[maxn << 2], ans;
struct Seg{int l, r, sum;
}seg[maxn << 2];inline int read(){int s = 0, w = 1;char c = getchar();for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);return s * w;
}inline int Read(){char c = getchar();for (; c != '.' && c != 'T'; c = getchar());return c == 'T';
}void pushup(int rt){ seg[rt].sum = seg[ls].sum + seg[rs].sum; }void pushdown(int rt){tag[ls] = tag[rs] = 1;seg[ls].sum = seg[ls].r - seg[ls].l + 1;seg[rs].sum = seg[rs].r - seg[rs].l + 1;
}void build(int rt, int l, int r){seg[rt].l = l, seg[rt].r = r;if (l == r) return;int mid = (l + r) >> 1;build(ls, l, mid); build(rs, mid + 1, r);
}void update(int rt, int l, int r){if (seg[rt].l > r || seg[rt].r < l) return;if (seg[rt].l >= l && seg[rt].r <= r){seg[rt].sum = seg[rt].r - seg[rt].l + 1;tag[rt] = 1;return;}if (tag[rt]) pushdown(rt);update(ls, l, r), update(rs, l, r);pushup(rt);
}int query(int rt, int l, int r){if (seg[rt].l > r || seg[rt].r < l) return 0;if (seg[rt].l >= l && seg[rt].r <= r) return seg[rt].r - seg[rt].l + 1 - seg[rt].sum;if (tag[rt]) pushdown(rt);return query(ls, l, r) + query(rs, l, r);pushup(rt);
}int main(){n = read(), st = read();for (int i = 1; i <= n; ++i) a[i] = read();for (int i = 1; i <= n; ++i) b[i] = Read(), cnt[i] = cnt[i - 1] + b[i];  peakl[1] = bottoml[1] = samel[1] = 1;int PEAK = 1, BOTTOM = 1;for (int i = 2; i <= n; ++i){if (a[i] <= a[i - 1]) peakl[i] = PEAK;else peakl[i] = PEAK = i;if (a[i] >= a[i - 1]) bottoml[i] = BOTTOM;else bottoml[i] = BOTTOM = i;if (a[i] == a[i - 1]) samel[i] = samel[i - 1];else samel[i] = i;}    peakr[n] = bottomr[n] = samer[n] = n;PEAK = BOTTOM = n;for (int i = n - 1; i; --i){if (a[i] <= a[i + 1]) peakr[i] = PEAK;else peakr[i] = PEAK = i;if (a[i] >= a[i + 1]) bottomr[i] = BOTTOM;else bottomr[i] = BOTTOM = i;if (a[i] == a[i + 1]) samer[i] = samer[i + 1];else samer[i] = i;}if (cnt[bottomr[st]] - cnt[bottoml[st] - 1] == 0){printf("%d\n", max(bottomr[st] - samel[st] + 1, samer[st] - bottoml[st] + 1));return 0;}build(1, 1, n);for (int i = 1; i <= n; ++i)if (b[i]){int L = peakl[i], R = peakr[i];if (L < i && R > i) continue;if (L < i) update(1, L, i); else update(1, i, R);}for (int i = 1; i <= n; ++i)if (b[i]){int L = peakl[i], R = peakr[i];update(1, L, R);}int ansl = 0, ansr = 0;for (int i = 1; i <= n; ++i)if (a[peakl[i]] == a[i] && a[peakr[i]] == a[i]){if (query(1, bottoml[i], i) > ans)ans = query(1, bottoml[i], i), ansl = bottoml[i], ansr = i;if (query(1, i, bottomr[i]) > ans)ans = query(1, i, bottomr[i]), ansl = i, ansr = bottomr[i];}update(1, ansl, ansr);printf("%d\n", n - query(1, 1, n));return 0;
}

【题解】LuoGu4611:[COI2012] TRAMPOLIN相关推荐

  1. [COI2012] TRAMPOLIN

    题目链接:[COI2012] TRAMPOLIN 建立一个传送点,然后变成某个点开始的种类最长路.但是存在环,所以我们可以缩点. 然后记忆化dfs或者拓扑即可. AC代码: #pragma GCC o ...

  2. 【题解】LuoGu4610:[COI2012] KAMPANJA

    原题传送门 先用floydfloydfloyd预处理出 wx,yw_{x,y}wx,y​表示x−>yx->yx−>y的最短路 所以x−>yx->yx−>y最少经过w ...

  3. [JS][dfs]题解 | #迷宫问题#

    题解 | #迷宫问题# 题目链接 迷宫问题 题目描述 定义一个二维数组 N*M ,如 5 × 5 数组下所示: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 1, 1 ...

  4. [JS][dp]题解 | #打家劫舍(一)#

    题解 | #打家劫舍(一)# 题目链接 打家劫舍(一) 题目描述 描述 你是一个经验丰富的小偷,准备偷沿街的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家, ...

  5. [JS]题解 | #魔法数字#

    题解 | #魔法数字# 题目链接 魔法数字 题目描述 牛妹给牛牛写了一个数字n,然后又给自己写了一个数字m,她希望牛牛能执行最少的操作将他的数字转化成自己的. 操作共有三种,如下: 在当前数字的基础上 ...

  6. [JS]题解 | #岛屿数量#

    题解 | #岛屿数量# 题目链接 岛屿数量 题目描述 时间限制:1秒 空间限制:256M 描述 给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛.我们只考虑上下左右 ...

  7. [JS] 题解:提取不重复的整数

    题解:提取不重复的整数 https://www.nowcoder.com/practice/253986e66d114d378ae8de2e6c4577c1 时间限制:1秒 空间限制:32M 描述 输 ...

  8. 洛谷-题解 P2672 【推销员】

    独门思路!链表加优先队列! 这题一望,贪心是跑不掉了,但是我贪心并不好,所以想到了一个复杂一些但思路更保稳的做法 思路: 1 因为是离线操作,所以我们可以倒着求,先求x=n的情况,因为那样直接就知道了 ...

  9. [洛谷1383]高级打字机 题解

    题解 这道题一看就珂以用主席树啊 这是一道神奇的题目,那么我们先敲一个主席树,然后维护一个数组len,表示下一次应该在len + 1插入, 之后对于T操作,在上一个版本的len + 1上直接执行插入 ...

最新文章

  1. Spring注解@Component和@resource的使用
  2. python代码没有错误却无法运行的原因-Python shell没有显示错误,但程序没有运行...
  3. python基础教程3-Python基础教程(三)
  4. 1138 Postorder Traversal (25 分)【难度: 一般 / 知识点: 建树】
  5. redis 内存不足 排查_Redis 系统学习之 redis 内存模型
  6. 信息系统项目管理基础(1)
  7. Java Hashtable equals()方法与示例
  8. Oracle 存储过程的创建,及触发器调用存储过程
  9. Thrift原理与使用实例
  10. 戴尔服务器安装群晖系统安装教程,实战群晖NAS小白安装教程与经验分享
  11. hping 详解_hping3 使用详解
  12. 正负数据如何归一化_数据归一化和两种常用的归一化方法
  13. WPF 鼠标滚轮对图片的缩放
  14. android 特殊符号
  15. Win7 共享打印机脱机解决
  16. open judge 1.7.1
  17. UI界面视觉设计之色彩要素
  18. 七牛云 Java Web上传图片
  19. 手把手学爬虫第六弹——数据可视化
  20. perl C/C++ 扩展(五)

热门文章

  1. 秋招面试!30K成功入职美团,忙里偷闲分享一波【面试经历+面试真题】
  2. oracle的字符集(NLS_LANGUAGE)
  3. 在Java中什么是IoC和DI?DI是如何实现的?
  4. 条码管理系统,助力企业打造轻量级数字化车间
  5. 【word】插入自动目录
  6. Excel两列数据去重
  7. css是什么和css选择器
  8. 5G时代系列谈:(五)未来之势
  9. 18. SPI协议,spi转can,MCP2515裸机驱动详解
  10. SpringBoot自定义异常,优雅解决业务逻辑中的错误