【2019银川网络赛】L:Continuous Intervals
题目大意:给定一个长度为 N 的序列,定义连续区间 [l, r] 为:序列的一段子区间,满足 [l, r] 中的元素从小到大排序后,任意相邻两项的差值不超过1。求一共有多少个连续区间。
题解:单调栈 + 线段树
首先,对于区间计数类问题常规的思路是枚举区间的左端点或右端点,统计以该点为端点的区间个数,加入答案贡献。
对于这道题来说,不妨枚举答案的右端点 r,那么对于每个 r,需要快速得出有多少个左端点 l,使得区间 [l, r] 满足连续区间的性质。若能在 \(O(logn)\) 的时间内得出答案即可解决本题。
根据连续区间的性质,可知连续区间的定义等价于
\]
其中,cnt 为区间 [l, r] 中不同数字的个数。可以发现,只有取得等号的时候才满足连续区间的性质,即:\(max - min - cnt = -1\)。因此,对于每个枚举到的右端点 r,我们需要知道每个小于 r 的 l, [l, r] 区间的最大值和最小值以及区间不同数的个数。
可以利用线段树维护 \(max - min - cnt\),只需维护区间最小值以及区间最小值的个数,即可在线段树上快速回答询问。
维护区间最值可以利用单调栈,即:第 i 个元素入栈时,栈内元素由于单调性,自然维护了区间[i, r] 的最值,每次从栈中弹出元素时,需要在线段树上修改维护的最值贡献。
维护区间颜色数是一个经典问题,即:维护一个 pre 数组,用于记录上一次某个元素出现的位置。
代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
struct node { // max - min - cnt >= -1
#define ls(o) t[o].lc
#define rs(o) t[o].rc
int lc, rc;
LL mi, cnt, add;
};
vector<node> t;
int tot, rt;
inline void up(int o) {
if (t[ls(o)].mi == t[rs(o)].mi) {
t[o].mi = t[ls(o)].mi;
t[o].cnt = t[ls(o)].cnt + t[rs(o)].cnt;
} else if (t[ls(o)].mi < t[rs(o)].mi) {
t[o].mi = t[ls(o)].mi;
t[o].cnt = t[ls(o)].cnt;
} else {
t[o].mi = t[rs(o)].mi;
t[o].cnt = t[rs(o)].cnt;
}
}
inline void down(int o) {
if (t[o].add != 0) {
t[ls(o)].mi += t[o].add, t[ls(o)].add += t[o].add;
t[rs(o)].mi += t[o].add, t[rs(o)].add += t[o].add;
t[o].add = 0;
}
}
inline int newnode() {
++tot;
t[tot].lc = t[tot].lc = t[tot].mi = t[tot].cnt = t[tot].add = 0;
return tot;
}
void build(int &o, int l, int r) {
o = newnode();
if (l == r) {
t[o].mi = t[o].add = 0, t[o].cnt = 1;
return;
}
int mid = l + r >> 1;
build(ls(o), l, mid);
build(rs(o), mid + 1, r);
up(o);
}
void modify(int o, int l, int r, int x, int y, LL add) {
if (l == x && r == y) {
t[o].mi += add, t[o].add += add;
return;
}
int mid = l + r >> 1;
down(o);
if (y <= mid) {
modify(ls(o), l, mid, x, y, add);
} else if (x > mid) {
modify(rs(o), mid + 1, r, x, y, add);
} else {
modify(ls(o), l, mid, x, mid, add);
modify(rs(o), mid + 1, r, mid + 1, y, add);
}
up(o);
}
int main() {
int T, kase = 0;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
t.resize(2 * n), tot = 0;
build(rt, 1, n);
vector<pair<int, int>> mi(n + 1), mx(n + 1);
int top1 = 0, top2 = 0;
map<int, int> pre;
LL ans = 0;
for (int i = 1, now; i <= n; i++) { // <val, pos>
now = i;
while (top1 > 0 && a[i] < mi[top1].first) {
int pos = mi[top1 - 1].second;
modify(rt, 1, n, pos + 1, now - 1, mi[top1].first - a[i]);
--top1;
now = pos + 1;
}
mi[++top1] = make_pair(a[i], i);
now = i;
while (top2 > 0 && a[i] > mx[top2].first) {
int pos = mx[top2 - 1].second;
modify(rt, 1, n, pos + 1, now - 1, a[i] - mx[top2].first);
--top2;
now = pos + 1;
}
mx[++top2] = make_pair(a[i], i);
if (pre.find(a[i]) != pre.end()) {
int pos = pre[a[i]];
modify(rt, 1, n, pos + 1, i, -1);
} else {
modify(rt, 1, n, 1, i, -1);
}
pre[a[i]] = i;
if (t[rt].mi == -1) {
ans += t[rt].cnt;
}
}
printf("Case #%d: %lld\n", ++kase, ans);
}
return 0;
}
【2019银川网络赛】L:Continuous Intervals的更多相关文章
- 2019南昌网络赛I:Yukino With Subinterval(CDQ) (树状数组套主席树)
题意:询问区间有多少个连续的段,而且这段的颜色在[L,R]才算贡献,每段贡献是1. 有单点修改和区间查询. 思路:46min交了第一发树套树,T了. 稍加优化多交几次就过了. 不难想到,除了L这个点, ...
- ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval
ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval 题目大意:给一个长度为n,值域为[1, n]的序列{a},要求支持m次操作: 单点修改 1 pos val 询 ...
- ICPC 2019 徐州网络赛
ICPC 2019 徐州网络赛 比赛时间:2019.9.7 比赛链接:The Preliminary Contest for ICPC Asia Xuzhou 2019 赛后的经验总结 // 比赛完才 ...
- 2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)
2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树) 传送门:https://nanti.jisuanke.com/t/41296 题意: 给一个数列A 问在数列A中有多 ...
- ACM-ICPC 2019南昌网络赛F题 Megumi With String
ACM-ICPC 南昌网络赛F题 Megumi With String 题目描述 给一个长度为\(l\)的字符串\(S\),和关于\(x\)的\(k\)次多项式\(G[x]\).当一个字符串\(str ...
- 2019 南京网络赛A
南京网络赛自闭现场 https://nanti.jisuanke.com/t/41298 二维偏序经典题型 二维前缀和!!! #include<bits/stdc++.h> using n ...
- 2018ICPC银川 L Continuous Intervals 单调栈 线段树
题意:给你一个序列,问你这个序列有多少个子区间,满足把区间里的数排序之后相邻两个数之间的差 <= 1 ? 思路:https://blog.csdn.net/u013534123/article/ ...
- 2019 ICPC 银川网络赛 D. Take Your Seat (疯子坐飞机问题)
Duha decided to have a trip to Singapore by plane. The airplane had nn seats numbered from 11 to nn, ...
- 2019 ICPC 银川网络赛 H. Fight Against Monsters
It is my great honour to introduce myself to you here. My name is Aloysius Benjy Cobweb Dartagnan Eg ...
随机推荐
- JavaScript参考DOM部分
目录 DOM完整版 DOM 介绍 节点 节点树 Node接口 属性 方法 NodeList 接口,HTMLCollection 接口 介绍 NodeList.prototype.length Node ...
- 【POJ - 3009】Curling 2.0 (dfs+回溯)
-->Curling 2.0 直接上中文 Descriptions: 今年的奥运会之后,在行星mm-21上冰壶越来越受欢迎.但是规则和我们的有点不同.这个游戏是在一个冰游戏板上玩的,上面有一个正 ...
- Windows下的开发辅助神器——Chocolate Package Manager
Windows下的开发辅助神器——Chocolate Package Manager:https://juejin.im/post/5c6cb3acf265da2dc4537235 Windows上的 ...
- JDK下bin文件夹常见几个可执行文件
bin目录下有很多的可执行文件: java.exe:运行Java程序,就是启动JVM,让JVM执行指定的编译后的代码: javac.exe:Java的编译器,它用于把Java源码文件(以.java后缀 ...
- 搭建本地parcel仓库
参考:https://www.cloudera.com/documentation/enterprise/6/6.2/topics/cm_ig_create_local_parcel_repo.htm ...
- Ubuntu关机等待时间解决方案
关于GDM问题(a stop job is running for session c1 of user root 1 min 30 s) 注意了,这个不是系统的问题,是配置的问题.鼓捣了老久才找出来 ...
- thinkphp6下无法获取header头中的Authorization(apache版)
今天遇到在thinkphp框架中获取不到header头里边的 Authorization ,后来在.htaccess里面加多一项解决,记录下: <IfModule mod_rewrite.c&g ...
- java native本地方法详解(转)
文章链接出处: 详解native方法的使用 自己实现一个Native方法的调用 JNI 开始本篇的内容之前,首先要讲一下JNI.Java很好,使用的人很多.应用极 广,但是Java不是完美的.Java ...
- 如何用纯 CSS 创作一个菜单反色填充特效
效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览.https://codepen.io/comehope/pen/qYMoPo 可交互视频教程 ...
- mybatis插入出现org.apache.ibatis.executor.ExecutorException: No setter found for the keyProperty 'xxx'异常的原因
确定有setter方法,问题其实是xml文件中,insert的主键的列名写错了,如下,一开始写成ComId <insert id="insertCom" parameterT ...