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. C. Ayoub and Lost Array

    链接 [https://codeforces.com/contest/1105/problem/C] 题意 给你n,表示数组长度,元素的值是l到r,问有多少种方案使得所有元素和整除3 分析 思维dp, ...

  2. AtCoder Beginner Contest 049 & ARC065 連結 / Connectivity AtCoder - 2159 (并查集)

    Problem Statement There are N cities. There are also K roads and L railways, extending between the c ...

  3. HTTPS建立连接的过程

    HTTP建立连接的过程点击:HTTP三次握手.一次HTTP请求都发生了什么 一.HTTPS   HTTP是超文本传输协议.HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私 ...

  4. 福州大学软件工程1816 | W班 第8次作业[团队作业,随堂小测——校友录]

    作业链接 团队作业,随堂小测--校友录 评分细则 本次个人项目分数由两部分组成(博客分满分40分+程序得分满分60分) 博客和程序得分表 评分统计图 千帆竞发图 总结 旅法师:实现了更新,导出,查询, ...

  5. 将iso镜像转换为docker镜像

    为什么不用官方的镜像? 不是不想使用,而是官方镜像提供的功能实在是太少了,不信的话,你pull一个ubuntu:latest的进行,你看有没有wget.curl.ssh这些功能,就连最简单的ifcon ...

  6. Jenkins+Docker自动化集成环境搭

    关于Docker Docker 简介 Docker现在是Github社区最火的项目之一,Docker是个容器,或许你听过lxc,你可能知道Tomcat这个Web容器,容器是什么概念,意会就好.问个问题 ...

  7. [转帖]NUMA架构的CPU -- 你真的用好了么?

    NUMA架构的CPU -- 你真的用好了么? 本文从NUMA的介绍引出常见的NUMA使用中的陷阱,继而讨论对于NUMA系统的优化方法和一些值得关注的方向. 文章欢迎转载,但转载时请保留本段文字,并置于 ...

  8. [转帖]国产紫光SSD不再只是实验室展品 开始批量出货

    国产紫光SSD不再只是实验室展品 开始批量出货 https://www.cnbeta.com/articles/tech/825865.htm 没听说有做HDD的 现做了SSD 弯道超车吗 可以实现全 ...

  9. CSS实现元素水平垂直居中

    我们知道,实现元素的水平居中比较简单,在设置了宽度后,设置左右margin为auto就可以. 但是如何设置元素垂直居中呢? 当然,对于单行的文字,可以通过设置line-height来解决, 可以对于一 ...

  10. ssh 登陆服务器原理

    这里分两种情况,这两种情况都涉及到公钥加密的概念. 由于公钥加密概念作为基础就不在本文进行讨论了. 使用ssh对远程服务器进行密码登录发生了什么: 客户端通过ssh连接服务器 1. 首先服务器把自己的 ...