CF997E. Good Subsegments

Description

给定一个序列,多次询问一个区间内的连续段个数。
n,q≤2×105n,q \leq 2\times 10^{5}n,q≤2×105

Solution

算得上是经典题了吧。

Part one

先考虑求全部的连续段个数。

相当于求区间内mx−mn+1−len=0mx - mn + 1 - len = 0mx−mn+1−len=0的子区间个数,且显然有mx−mn+1−len≥0mx - mn + 1 - len \geq 0mx−mn+1−len≥0,因此相当于维护最小值及其个数。于是我们考虑从前往后枚举区间右端点rrr,维护所有右端点为rrr的区间的信息。

不难观察到前缀mxmxmx和前缀mnmnmn的单调性,每次我们加入一个prp_rpr​时,会让一段后缀的mxmxmx和一段后缀的mnmnmn改变,且改变的这一段后缀mxmxmx会变成prp_rpr​,mnmnmn同理。于是我们用单调栈分别维护前缀mx,mnmx,mnmx,mn的连续段,每次弹栈的时候做区间加就可以维护我们需要的信息了。

这样的时间复杂度是O(mlgn)O(mlgn)O(mlgn)的。

Part two

再考虑区间询问,上述枚举右端点的做法启示我们离线询问。考虑每个右端点的询问,限制[l,r][l,r][l,r]相当于是只能统计左端点在lll后面的连续段。

然后我们考虑维护clc_lcl​表示当前右端点为rrr(枚举的右端点),左端点为lll的连续段个数,然后询问就是一段区间和。这个直接在线段树上打tagtagtag,表示这个区间的最小值为000的点都有多少次新增的贡献即可维护。

实现时注意下传tagtagtag的标记即可。
时间复杂度O(mlgn)O(mlgn)O(mlgn)。

Code

#include <bits/stdc++.h>using namespace std;template<typename T> inline bool upmin(T &x, T y) { return y < x ? x = y, 1 : 0; }
template<typename T> inline bool upmax(T &x, T y) { return x < y ? x = y, 1 : 0; }#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondtypedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int, int> PR;
typedef vector<int> VI; const lod eps = 1e-9;
const lod pi = acos(-1);
const int oo = 1 << 30;
const ll loo = 1ll << 62;
const int mods = 1e9 + 7;
const int MAXN = 300005;
const int INF = 0x3f3f3f3f; //1061109567
/*--------------------------------------------------------------------*/namespace FastIO{constexpr int SIZE = (1 << 21) + 1;int num = 0, f;char ibuf[SIZE], obuf[SIZE], que[65], *iS, *iT, *oS = obuf, *oT = obuf + SIZE - 1, c;#define gc() (iS == iT ? (iT = ((iS = ibuf) + fread(ibuf, 1, SIZE, stdin)), (iS == iT ? EOF : *iS ++)) : *iS ++)inline void flush() {fwrite(obuf, 1, oS - obuf, stdout);oS = obuf;}inline void putc(char c) {*oS ++ = c;if (oS == oT) flush();}inline void getc(char &c) {for (c = gc(); c < 'A' || c > 'Z' ; c = gc());}template<class I>inline void read(I &x) {for (f = 1, c = gc(); c < '0' || c > '9' ; c = gc()) if (c == '-') f = -1;for (x = 0; c >= '0' && c <= '9' ; c = gc()) x = (x << 3) + (x << 1) + (c & 15);x *= f;}template<class I>inline void print(I x) {if (x < 0) putc('-'), x = -x;if (!x) putc('0');while (x) que[++ num] = x % 10 + 48, x /= 10;while (num) putc(que[num --]);}struct Flusher_{~Flusher_(){flush();}} io_Flusher_;
}
using FastIO :: read;
using FastIO :: print;
using FastIO :: putc;ll Ans[MAXN], c[MAXN << 2], tagc[MAXN << 2];
int MX = 0, tag[MAXN << 2], mn[MAXN << 2], s[MAXN << 2], stkmx[MAXN], stkmn[MAXN], p[MAXN];
void up(int x) {mn[x] = min(mn[x << 1], mn[x << 1 | 1]);s[x] = (mn[x << 1] == mn[x]) * s[x << 1] + (mn[x << 1 | 1] == mn[x]) * s[x << 1 | 1];
}
void down(int x) {if (tag[x] != 0) {mn[x << 1] += tag[x], mn[x << 1 | 1] += tag[x]; tag[x << 1] += tag[x], tag[x << 1 | 1] += tag[x];tag[x] = 0;}if (tagc[x] != 0) {if (mn[x << 1] == mn[x]) c[x << 1] += tagc[x] * s[x << 1], tagc[x << 1] += tagc[x];if (mn[x << 1 | 1] == mn[x]) c[x << 1 | 1] += tagc[x] * s[x << 1 | 1], tagc[x << 1 | 1] += tagc[x];tagc[x] = 0;}
}
void build(int x, int l, int r) {if (l == r) { mn[x] = r - l + 1, s[x] = 1; return; }int mid = (l + r) >> 1;build(x << 1, l, mid);build(x << 1 | 1, mid + 1, r);up(x);
}
void update(int x, int l, int r, int L, int R, int y) {if (l >= L && r <= R) { mn[x] += y, tag[x] += y;  return; }down(x);int mid = (l + r) >> 1;if (R <= mid) update(x << 1, l, mid, L, R, y);else if (L > mid) update(x << 1 | 1, mid + 1, r, L, R, y);else update(x << 1, l, mid, L, mid, y), update(x << 1 | 1, mid + 1, r, mid + 1, R, y);up(x);
}
ll query(int x, int l, int r, int L, int R) {if (l >= L && r <= R) return c[x];down(x);int mid = (l + r) >> 1;if (R <= mid) return query(x << 1, l, mid, L, R);else if (L > mid) return query(x << 1 | 1, mid + 1, r, L, R);else return query(x << 1, l, mid, L, mid) + query(x << 1 | 1, mid + 1, r, mid + 1, R);
}
struct Qnode{ int l, r, id; } Q[MAXN];
signed main() {
#ifndef ONLINE_JUDGEfreopen("a.in", "r", stdin);
#endifint n, m; read(n);for (int i = 1; i <= n ; ++ i) read(p[i]);read(m);for (int i = 1; i <= m ; ++ i) read(Q[i].l), read(Q[i].r), Q[i].id = i;sort(Q + 1, Q + m + 1, [&](Qnode x, Qnode y){ return x.r < y.r; });build(1, 1, n);    for (int i = 1, topmx = 0, topmn = 0, nw = 1; i <= n ; ++ i) {while (topmx && p[stkmx[topmx]] < p[i]) update(1, 1, n, stkmx[topmx - 1] + 1, stkmx[topmx], -p[stkmx[topmx]]), -- topmx;while (topmn && p[stkmn[topmn]] > p[i]) update(1, 1, n, stkmn[topmn - 1] + 1, stkmn[topmn], p[stkmn[topmn]]), -- topmn;update(1, 1, n, 1, i, -1);update(1, 1, n, stkmx[topmx] + 1, i, p[i]);update(1, 1, n, stkmn[topmn] + 1, i, -p[i]);stkmx[++ topmx] = i;stkmn[++ topmn] = i;down(1), ++ tagc[1], c[1] += s[1];while (nw <= m && Q[nw].r == i) Ans[Q[nw].id] = query(1, 1, n, Q[nw].l, i), ++ nw;}for (int i = 1; i <= m ; ++ i) print(Ans[i]), putc('\n');return 0;
}

CF997E. Good Subsegments(线段树,单调栈)相关推荐

  1. CF407 E. k-d-sequence(线段树+单调栈)

    文章目录 CF407 E. k-d-sequence problem solution code CF407 E. k-d-sequence problem solution special case ...

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

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

  3. [线段树][单调栈] BZOJ 4527 CF 407E: K-D-Sequence

    SolutionSolution 可以把同余的串一起考虑,然后把所有数除以dd.变成公差为11的情况. 满足这样的条件 MAXL≤i≤RAi−MINL≤i≤RAi−R≤k−L MAX_{L\le i\ ...

  4. 【BZOJ-28921171】强袭作战大sz的游戏 权值线段树+单调队列+标记永久化+DP...

    2892: 强袭作战 Time Limit: 50 Sec  Memory Limit: 512 MB Submit: 45  Solved: 30 [Submit][Status][Discuss] ...

  5. Breaking Down News【HDU-6856】【线段树+单调队列/栈】

    2020 Multi-University Training Contest 8 B 有N个权值,每个权值只能是{-1, 0, 1}中的一个,然后现在分成几段区间,每一段的长度在[L, R]之间,每一 ...

  6. POJ - 2201 Cartesian Tree(笛卡尔树-单调栈/暴跳父亲)

    题目链接:点击查看 题目大意:给出n个节点的key和val,构造出其笛卡尔树的原型 笛卡尔树的定义: 所谓笛卡尔树,就是将给定的n个二元组(key,val)建成一棵树.使得: 如果只关注key,那么这 ...

  7. P3714 [BJOI2017]树的难题(点分治/线段树/单调队列)

    P3714 [BJOI2017]树的难题 求解树上长度在L到R的树链中颜色段权值和最大的链. 首先求解树上链的问题,而且限制了链的长度,那么我们需要点分治处理,然后考虑每次分治,我们可以把链分成两类, ...

  8. LOJ 534 花团(线段树+dfs栈)

    题意 https://loj.ac/problem/534 思路 又是复杂度错误的一题,\(O(n^2\log n)\) 能过 \(15000\) . 虽然看起来强制在线,其实是一道假的在线题.首先按 ...

  9. CF #669 (Div. 2)D. Discrete Centrifugal Jumps(线段树/单调队列优化dp)

    https://codeforces.com/contest/1407/problem/D 题意:给定n个高度,当i<ji<ji<j且满足以下条件之一时,可以从iii跳到jjj: 问 ...

最新文章

  1. MinkowskiPooling池化(上)
  2. Windows和Linux下通用的线程接口
  3. SQL——以面向集合的思维方式来思考
  4. 通过特征类型超参数控制权重类型
  5. 最后一个 IPV4 地址分配完毕,正式向IPV6过渡!
  6. Eclipse | 使用
  7. /UI5/IF_UI5_REP_PERSISTENCE - why I cannot deploy app to GM6
  8. php之clone 复制对象以及__clone魔术方法
  9. dynamic web module消失不见
  10. Java jdk中的部分工具javac javaw javaws javadoc javah javap jar jdb jps的作用
  11. 公众号H5 VUE获取CODE
  12. 【Python】Python迭代求解开平方算法
  13. 访问自己的网站有病毒提示,为什么?
  14. obs计算机丢失,安装obs时提醒没法启动此程序,因为计算机丢失
  15. 946. Validate Stack Sequences验证栈序列
  16. 剪切板是计算机系统,剪贴板
  17. FYI | Neuro Workshop (Virtual)-Connectomics
  18. Pyton学习—循环语句
  19. homelede软路由设置方法_低成本组装一台LEDE软路由
  20. 大盘为何回血以及盐湖股份和科达制造

热门文章

  1. 第4章 字符串和格式化输入/输出
  2. 这个小姐姐真的很火辣......
  3. 女朋友竟然提出这种奇怪的要求......
  4. 漫谈高数——泰勒级数的物理意义
  5. java里面什么时候环境变量_Java的环境变量什么时候需要设置?
  6. 巴比伦算法求平方根c语言,巴比伦算法求平方根
  7. mysql isam 食物_MySQL常用存储引擎之MyISAM
  8. java蛮力法背包问题_[算法课]五种蛮力法解决01背包问题
  9. html点击按钮计算两个输入框的和_小程序计算报价功能介绍
  10. 织梦手机版list.php,解决织梦一级目录作域名list.php无法跳转到手机站的问题