Description

原题链接

给你一个长度为\(n\)的排列\(~P\),定义一段子区间是好的,当且仅当这个子区间内的值构成了连续的一段。例如对于排列\(\{1,3,2 \}\),\([1, 1], [2, 2], [3, 3], [2, 3], [1, 3]\)是好的区间。

共\(q\)次询问,每次询问\(L,R\), 求有多少\(L \leq l \leq r \leq R\),满足\([l, r]\)是好的区间。\(1 \leq n, q \leq 1.2 \times 10 ^ 5\).

Solution

可以发现,区间\([l, r]\)是好的,当且仅当\(~(Max_{i = l}^{r} - Min_{i = l} ^ {r}) - (r - l) = 0\).

考虑维护一段区间上式的最小值(以下的最小值都指上式最小值),每一个最小值为\(0\)的位置都可以和当前的\(r\)组成一个好的区间。不难发现,一个右端点能产生的贡献为它左边的点的最小值为\(0\)的个数,于是可以在线段树上维护最小值和最小值个数,以及每个最小值为\(0\)的位置产生的贡献。

由于右边新加的点会对已有的点产生影响,考虑离线询问,按右端点排序,用两个单调栈分别维护当前\(Min\)和\(Max\)。右端点右移时,势必会使整个区间的最小值减一,也势必会使其未右移前的右端点对答案产生一轮贡献,每次处理右端点等于当前枚举点的答案。时间复杂度\(O(n \log n)\).

Code

#include <bits/stdc++.h>

#define For(i, j, k) for (int i = j; i <= k; ++ i)
#define Forr(i, j, k) for (int i = j; i >= k; -- i) using namespace std; typedef long long ll; inline int read() {
int x = 0, p = 1; char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') p = -1;
for (; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * p;
} inline void File() {
freopen("CF997E.in", "r", stdin);
freopen("CF997E.out", "w", stdout);
} const int N = 1.2e5 + 10;
int n, q, a[N], s1[N], t1, s2[N], t2, tt = 1; ll ans[N]; struct Query {
int id, l, r;
bool operator < (const Query &rhs) const { return r < rhs.r; }
} Q[N]; namespace Segment_Tree {
#define lc (rt << 1)
#define rc (rt << 1 | 1)
#define mid (l + r >> 1) const int MAXN = N << 2;
int mn[MAXN], tag[MAXN], t[MAXN]; ll sum[MAXN], tg[MAXN]; inline void pushdown(int rt) {
if (tag[rt]) {
mn[lc] += tag[rt], mn[rc] += tag[rt];
tag[lc] += tag[rt], tag[rc] += tag[rt];
tag[rt] = 0;
} if (tg[rt]) {
if (mn[lc] == mn[rt]) sum[lc] += 1ll * t[lc] * tg[rt], tg[lc] += tg[rt];
if (mn[rc] == mn[rt]) sum[rc] += 1ll * t[rc] * tg[rt], tg[rc] += tg[rt];
tg[rt] = 0;
}
} inline void pushup(int rt) {
t[rt] = 0, mn[rt] = min(mn[lc], mn[rc]); t[rt] = mn[rt] == mn[lc] ? t[rt] + t[lc] : t[rt];
t[rt] = mn[rt] == mn[rc] ? t[rt] + t[rc] : t[rt]; sum[rt] = sum[lc] + sum[rc];
} inline void Build(int rt, int l, int r) {
mn[rt] = l, t[rt] = 1;
if (l ^ r) Build(lc, l, mid), Build(rc, mid + 1, r);
} inline void update(int rt, int l, int r, int L, int R, int v) {
if (L <= l && r <= R) { mn[rt] += v, tag[rt] += v; return ; }
pushdown(rt); if (L <= mid) update(lc, l, mid, L, R, v);
if (R > mid) update(rc, mid + 1, r, L, R, v); pushup(rt);
} inline ll query(int rt, int l, int r, int L, int R) {
if (L <= l && r <= R) return sum[rt]; pushdown(rt);
if (R <= mid) return query(lc, l, mid, L, R);
if (L > mid) return query(rc, mid + 1, r, L, R);
return query(lc, l, mid, L, R) + query(rc, mid + 1, r, L, R);
} #undef lc
#undef rc
#undef mid
} int main() {
File(); using namespace Segment_Tree; n = read(); For(i, 1, n) a[i] = read();
q = read(); For(i, 1, q) Q[i].l = read(), Q[i].r = read(), Q[i].id = i; sort(Q + 1, Q + 1 + q); Build(1, 1, n); For(nr, 1, n) { mn[1] -= 1, tag[1] -= 1; for (; t1 && a[s1[t1]] < a[nr]; -- t1)
update(1, 1, n, s1[t1 - 1] + 1, s1[t1], a[nr] - a[s1[t1]]);
s1[++ t1] = nr; for (; t2 && a[s2[t2]] > a[nr]; -- t2)
update(1, 1, n, s2[t2 - 1] + 1, s2[t2], a[s2[t2]] - a[nr]);
s2[++ t2] = nr; sum[1] += t[1], tg[1] += 1; for (; tt <= q && Q[tt].r == nr; ++ tt)
ans[Q[tt].id] = query(1, 1, n, Q[tt].l, nr);
} For(i, 1, q) printf("%lld\n", ans[i]); return 0;
}

【CF997E】Good Subsegments (线段树+单调栈)的更多相关文章

  1. Codeforces 781E Andryusha and Nervous Barriers 线段树 单调栈

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF781E.html 题目传送门 - CF781E 题意 有一个矩形,宽为 w ,高为 h .一开始会有 w 个 ...

  2. 洛谷P4425 转盘 [HNOI/AHOI2018] 线段树+单调栈

    正解:线段树+单调栈 解题报告: 传送门! 1551又是一道灵巧连题意都麻油看懂的题,,,,所以先解释一下题意好了,,,, 给定一个n元环 可以从0时刻开始从任一位置出发 每次可以选择向前走一步或者在 ...

  3. 线段树+单调栈+前缀和--2019icpc南昌网络赛I

    线段树+单调栈+前缀和--2019icpc南昌网络赛I Alice has a magic array. She suggests that the value of a interval is eq ...

  4. 牛客多校第四场sequence C (线段树+单调栈)

    牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...

  5. Codeforces 1175F - The Number of Subpermutations(线段树+单调栈+双针/分治+启发式优化)

    Codeforces 题面传送门 & 洛谷题面传送门 由于这场的 G 是道毒瘤题,蒟蒻切不动就只好来把这场的 F 水掉了 看到这样的设问没人想到这道题吗?那我就来发篇线段树+单调栈的做法. 首 ...

  6. [Codeforces1132G]Greedy Subsequences——线段树+单调栈

    题目链接: Codeforces1132G 题目大意:给定一个序列$a$,定义它的最长贪心严格上升子序列为$b$满足若$a_{i}$在$b$中则$a_{i}$之后第一个比它大的也在$b$中.给出一个数 ...

  7. BZOJ.4540.[HNOI2016]序列(莫队/前缀和/线段树 单调栈 RMQ)

    BZOJ 洛谷 ST表的一二维顺序一定要改过来. 改了就rank1了哈哈哈哈.自带小常数没办法. \(Description\) 给定长为\(n\)的序列\(A_i\).\(q\)次询问,每次给定\( ...

  8. AtCoder Regular Contest 063 F : Snuke’s Coloring 2 (线段树 + 单调栈)

    题意 小 \(\mathrm{C}\) 很喜欢二维染色问题,这天他拿来了一个 \(w × h\) 的二维平面 , 初始时均为白色 . 然后他在上面设置了 \(n\) 个关键点 \((X_i , Y_i ...

  9. cdqz2017-test10-rehearsal(CDQ分治&可持久化线段树&单调栈)

    题意: 给出n个三元组 e[i]=(si,ti,wi) 第i个三元组的价值为 Σ w[j] ,j 满足以下4个条件: 1.j<i 2.tj<ti 3.sj<si 4.不存在j< ...

随机推荐

  1. 安装配置JDK和Eclipse的步骤

    导读 作为Java程序员,需要在Linux系统上安装Eclipse,很多人不知要如何安装,在安装Eclipse前,还需安装JDK,Linux下如何安装JDK和Eclipse呢?下面跟朋友们介绍下Lin ...

  2. Diverse Garland CodeForces - 1108D (贪心+暴力枚举)

    You have a garland consisting of nn lamps. Each lamp is colored red, green or blue. The color of the ...

  3. ubuntu中搭建svn服务器步骤

    1.安装软件包: sudo apt-get install subversion 2.建立相关文件夹(这里svn放在home文件夹中) cd /home sudo mkdir svn cd /home ...

  4. MySQL 通过多个示例学习索引

    最近在准备面试,关于索引这一块,发现很多以前忽略的点,这里好好整理一下 首先为什么要建立索引 一本书,有章.节.段.行这种单位. 如果现在需要找一个内容:第9章>第2节>第3段>第4 ...

  5. JavaScript实现文字跑马灯

    其实实现文字的跑马灯和实现图片轮播的原理是一样的. 下面是我自己实现的,文字的位置可以随便更改,效果不会变,文字的内容可以通过ajax获取,同时,可以直接用Jquery改写一下,很方便. <!D ...

  6. 深入解读Promise对象

    promise对象初印象: promise对象是异步编程的一种解决方案,传统的方法有回调函数和事件,promise对象是一个容器,保存着未来才会结束的事件的结果 promise对象有两个特点: 1.p ...

  7. [转帖]你所不知道的C和C++运行库

    [C-C++]你所不知道的C和C++运行库 https://blog.csdn.net/humanking7/article/details/85887884 原作者也是转的blog 最近一个物理机上 ...

  8. github上测试服出现bug,如何回滚并获得合并之前的分支

    使用场景: 当我们提交了一个pr,但是该pr合并之后,经过在测试测试有问题,需要回滚.这个时候主master代码将会被回滚到提交你的pr之前的代码.而你的pr由于已经被合并过了,所以无法继续提交. 这 ...

  9. Python2.7从入门到精通

    快速入门 1.程序输出print语句 (1)使用print语句可查看对象的值:在交互式解释器使用对象本身则输出此对象的字符串表示: (2)使用print语句调用str()显示对象:在交互式解释器使用对 ...

  10. react 入坑笔记(二) - State

    React State 一. state 大致思想:在 react 中,每个组件都是一个状态机,通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致.React 里,只需更新组件的 ...