2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)

传送门:https://nanti.jisuanke.com/t/41296

题意:

给一个数列A

问在数列A中有多少个区间满足,区间内数字排序后是一段连续的连续的区间

即排序后区间内的任意元素满足 \(a_{i+1}-a_i<=1\)

题解:

根据题意可知

满足题意的区间应当满足以下性质:

\(max-min==num-1\)

即当前区间最大的数字减去当前区间最小的数字等于区间数字的种类数

我们枚举区间的右端点\(R_i\),那么问题就转换为了有多少个\(L_j,j<=i\)

在区间\(L_j,R_i\)中,

\(Max-Min-num==-1\)

我们需要快速的得到所有满足上式\(L_j\)的个数

也就是 我们需要快速的得到区间 \([1,R_i]\)内满足上式的个数

我们可以用线段树来维护\(Max-Min-num\)这个值

查询就查询有多少个L对应这个值,如果\(Max-Min-num==-1\)

那么对应的值的个数可以对答案产生贡献

线段树维护\(Max-Min-num\)这个值时

我们可以用两个单调栈分别维护Max和Min的值,用map来维护区间数字出现的位置

对于每一次\(Max\)值的更新来说,我们需要减去当前的最大值a[i]-要删去的值的最大值staMax[tp]

对于每一次\(Min\)值的更新来说,我们需要减去要删去的值的最小值staMin[tp]-当前的最小值a[i]

对于每一次出现的数字,他的种类数可能会改变,我们需要在他上一次出现的位置到这个位置这个区间上-1

在查询的时候,我们只需要得到对应的\(Max-Min- num\)最小值为-1的个数即可

代码:

  1. /**
  2. *        ┏┓    ┏┓
  3. *        ┏┛┗━━━━━━━┛┗━━━┓
  4. *        ┃       ┃  
  5. *        ┃   ━    ┃
  6. *        ┃ >   < ┃
  7. *        ┃       ┃
  8. *        ┃... ⌒ ...  ┃
  9. *        ┃       ┃
  10. *        ┗━┓   ┏━┛
  11. *          ┃   ┃ Code is far away from bug with the animal protecting          
  12. *          ┃   ┃ 神兽保佑,代码无bug
  13. *          ┃   ┃           
  14. *          ┃   ┃       
  15. *          ┃   ┃
  16. *          ┃   ┃           
  17. *          ┃   ┗━━━┓
  18. *          ┃       ┣┓
  19. *          ┃       ┏┛
  20. *          ┗┓┓┏━┳┓┏┛
  21. *           ┃┫┫ ┃┫┫
  22. *           ┗┻┛ ┗┻┛
  23. */
  24. // warm heart, wagging tail,and a smile just for you!
  25. //
  26. // _ooOoo_
  27. // o8888888o
  28. // 88" . "88
  29. // (| -_- |)
  30. // O\ = /O
  31. // ____/`---'\____
  32. // .' \| |// `.
  33. // / \||| : |||// \
  34. // / _||||| -:- |||||- \
  35. // | | \ - /// | |
  36. // | \_| ''\---/'' | |
  37. // \ .-\__ `-` ___/-. /
  38. // ___`. .' /--.--\ `. . __
  39. // ."" '< `.___\_<|>_/___.' >'"".
  40. // | | : `- \`.;`\ _ /`;.`/ - ` : | |
  41. // \ \ `-. \_ __\ /__ _/ .-` / /
  42. // ======`-.____`-.___\_____/___.-`____.-'======
  43. // `=---='
  44. // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  45. // 佛祖保佑 永无BUG
  46. #include <set>
  47. #include <map>
  48. #include <stack>
  49. #include <cmath>
  50. #include <queue>
  51. #include <cstdio>
  52. #include <string>
  53. #include <vector>
  54. #include <cstring>
  55. #include <iostream>
  56. #include <algorithm>
  57. using namespace std;
  58. typedef long long LL;
  59. typedef pair<int, int> pii;
  60. typedef unsigned long long uLL;
  61. #define ls rt<<1
  62. #define rs rt<<1|1
  63. #define lson l,mid,rt<<1
  64. #define rson mid+1,r,rt<<1|1
  65. #define bug printf("*********\n")
  66. #define FIN freopen("input.txt","r",stdin);
  67. #define FON freopen("output.txt","w+",stdout);
  68. #define IO ios::sync_with_stdio(false),cin.tie(0)
  69. #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
  70. #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
  71. #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
  72. const int maxn = 1e5 + 5;
  73. const int INF = 0x3f3f3f3f;
  74. const int mod = 1e9 + 7;
  75. const double Pi = acos(-1);
  76. LL gcd(LL a, LL b) {
  77. return b ? gcd(b, a % b) : a;
  78. }
  79. LL lcm(LL a, LL b) {
  80. return a / gcd(a, b) * b;
  81. }
  82. double dpow(double a, LL b) {
  83. double ans = 1.0;
  84. while(b) {
  85. if(b % 2)ans = ans * a;
  86. a = a * a;
  87. b /= 2;
  88. } return ans;
  89. }
  90. LL quick_pow(LL x, LL y) {
  91. LL ans = 1;
  92. while(y) {
  93. if(y & 1) {
  94. ans = ans * x % mod;
  95. } x = x * x % mod;
  96. y >>= 1;
  97. } return ans;
  98. }
  99. /*
  100. 给你长为 1e5的数组,
  101. 要你求其中有多少个区间使得这个区间中的值域是个连续的区间,
  102. 即排序后两两个值的差小于等于1。
  103. */
  104. int Min[maxn << 2];
  105. int num[maxn << 2];
  106. int lazy[maxn << 2];
  107. void push_up(int rt) {
  108. Min[rt] = min(Min[ls], Min[rs]);
  109. if(Min[ls] == Min[rs]) {
  110. num[rt] = num[ls] + num[rs];
  111. } else if(Min[rt] == Min[ls]) {
  112. num[rt] = num[ls];
  113. } else {
  114. num[rt] = num[rs];
  115. }
  116. }
  117. void build(int l, int r, int rt) {
  118. Min[rt] = 0;
  119. lazy[rt] = 0;
  120. num[rt] = r - l + 1;
  121. if(l == r) {
  122. return;
  123. }
  124. int mid = (l + r) >> 1;
  125. build(lson);
  126. build(rson);
  127. // push_up(rt);
  128. }
  129. void push_down(int rt) {
  130. if(lazy[rt]) {
  131. lazy[ls] += lazy[rt];
  132. lazy[rs] += lazy[rt];
  133. Min[ls] += lazy[rt];
  134. Min[rs] += lazy[rt];
  135. lazy[rt] = 0;
  136. }
  137. }
  138. void update(int L, int R, int val, int l, int r, int rt) {
  139. if(L <= l && r <= R) {
  140. Min[rt] += val;
  141. lazy[rt] += val;
  142. return;
  143. }
  144. push_down(rt);
  145. int mid = (l + r) >> 1;
  146. if(L <= mid) update(L, R, val, lson);
  147. if(R > mid) update(L, R, val, rson);
  148. push_up(rt);
  149. }
  150. pii query(int L, int R, int l, int r, int rt) {
  151. if(L <= l && r <= R) {
  152. return make_pair(Min[rt], num[rt]);
  153. }
  154. push_down(rt);
  155. int mid = (l + r) >> 1;
  156. pii tmp1 = make_pair(INF, 0), tmp2 = make_pair(INF, 0);
  157. if(L <= mid) {
  158. tmp1 = query(L, R, lson);
  159. }
  160. if(R > mid) {
  161. tmp2 = query(L, R, rson);
  162. }
  163. pii ans;
  164. if(tmp1.first == tmp2.first) {
  165. ans = make_pair(tmp1.first, tmp1.second + tmp2.second);
  166. return ans;
  167. }
  168. if(tmp1.first < tmp2.first) {
  169. ans = tmp1;
  170. return ans;
  171. } else {
  172. ans = tmp2;
  173. return ans;
  174. }
  175. return ans;
  176. }
  177. int a[maxn];
  178. pii Maxsta[maxn], Minsta[maxn];
  179. map<int, int>mp;
  180. int main() {
  181. #ifndef ONLINE_JUDGE
  182. FIN
  183. #endif
  184. int T;
  185. scanf("%d", &T);
  186. int cas = 1;
  187. while(T--) {
  188. int n;
  189. int tpMax = 0;
  190. int tpMin = 0;
  191. scanf("%d", &n);
  192. build(1, n, 1);
  193. mp.clear();
  194. LL ans = 0;
  195. for(int i = 1; i <= n; i++) {
  196. scanf("%d", &a[i]);
  197. }
  198. for(int i = 1; i <= n; i++) {
  199. // mp[a[i]] = i;
  200. while(tpMax > 0 && Maxsta[tpMax].first < a[i]) {
  201. //减去小于当前值的Max贡献
  202. update(Maxsta[tpMax - 1].second + 1, Maxsta[tpMax].second, a[i] - Maxsta[tpMax].first, 1, n, 1);
  203. tpMax--;
  204. }
  205. Maxsta[++tpMax] = make_pair(a[i], i);
  206. while(tpMin > 0 && Minsta[tpMin].first > a[i]) {
  207. //减去大于当前值的Min贡献
  208. update(Minsta[tpMin - 1].second + 1, Minsta[tpMin].second, Minsta[tpMin].first - a[i], 1, n, 1);
  209. tpMin--;
  210. }
  211. Minsta[++tpMin] = make_pair(a[i], i);
  212. //减去重复数字的贡献
  213. update(mp[a[i]] + 1, i, -1, 1, n, 1);
  214. mp[a[i]] = i;
  215. pii flag = query(1, i, 1, n, 1);
  216. if(flag.first == -1) {
  217. ans += flag.second;
  218. }
  219. }
  220. printf("Case #%d: %lld\n", cas++, ans);
  221. }
  222. return 0;
  223. }

2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)的更多相关文章

  1. 2018ICPC银川 L Continuous Intervals 单调栈 线段树

    题意:给你一个序列,问你这个序列有多少个子区间,满足把区间里的数排序之后相邻两个数之间的差 <= 1 ? 思路:https://blog.csdn.net/u013534123/article/ ...

  2. 2018宁夏邀请赛L Continuous Intervals

    题目链接:https://nanti.jisuanke.com/t/28412 题意: 给出n个数的序列.问序列中有多少个区间满足,排序完之后任意两个相邻的数之差不大于1. 题解: 用max表示区间最 ...

  3. 2018宁夏邀请赛 L. Continuous Intervals

    转化一下询问即为区间$max - min + 1 = cnt$,其中$cnt$表示区间内数的种类数. 即求有多少区间$max - min - cnt=-1$,注意到任意区间的$max-min-cnt ...

  4. 南昌邀请赛I.Max answer 单调栈+线段树

    题目链接:https://nanti.jisuanke.com/t/38228 Alice has a magic array. She suggests that the value of a in ...

  5. 洛谷P4198 楼房重建 单调栈+线段树

    正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...

  6. 2018宁夏邀请赛 Continuous Intervals(单调栈 线段树

    https://vjudge.net/problem/Gym-102222L 题意:给你n个数的序列,让判断有几个区间满足排完序后相邻两数差都不大于1. 题解:对于一个区间 [L,R],记最大值为 m ...

  7. 2019ICPC南昌邀请赛网络赛 I. Max answer (单调栈+线段树/笛卡尔树)

    题目链接 题意:求一个序列的最大的(区间最小值*区间和) 线段树做法:用单调栈求出每个数两边比它大的左右边界,然后用线段树求出每段区间的和sum.最小前缀lsum.最小后缀rsum,枚举每个数a[i] ...

  8. The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer (单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题目大意:一个区间的值等于该区间的和乘以区间的最小值.给出一个含有n个数的序列(序列的值有正有负),找到该序列的区间最大 ...

  9. 2019南昌网络赛-I(单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题意:定义一段区间的值为该区间的和×该区间的最小值,求给定数组的最大的区间值. 思路:比赛时还不会线段树,和队友在这题上 ...

随机推荐

  1. easyUI + servlet 展示datagrid数据列表

    1:在jsp页面添加所用easyUI的js和css 2.前台代码示例: <table id="dgObj" style="width: 100%;height:90 ...

  2. Python中的生产者消费者模型

    ---恢复内容开始--- 了解知识点: 1.守护进程: ·什么是守护进程: 守护进程其实就是一个‘子进程’,守护即伴随,守护进程会伴随主进程的代码运行完毕后而死掉 ·为何用守护进程: 当该子进程内的代 ...

  3. 2016 Asia Jakarta Regional Contest J - Super Sum UVALive - 7720 【快速幂+逆元】

    J-Super Sum 题目大意就是给定N个三元组<a,b,c>求Σ(a1^k1*a2^k2*...*ai^ki*..an^kn)(bi<=ki<=ci) 唉.其实题目本身不难 ...

  4. Java练习 SDUT-1131_最大公约数与最小公倍数

    C/C++训练1---最大公约数与最小公倍数 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 输入两个正整数,求它们的最 ...

  5. HDU-1069_Monkey and Banana

    Monkey and Banana Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) P ...

  6. Python基础:17类和实例之一(类属性和实例属性)

    1:类通常在一个模块的顶层进行定义.对于Python来说,声明与定义类是同时进行的. 2:类属性仅与其类相绑定,类数据属性仅当需要有更加“静态”数据类型时才变得有用,这种属性是静态变量.它们表示这些数 ...

  7. HZOJ 辣鸡(ljh)

    题解?noipT1还需要题解?正解就是$n^2$大暴力. 考试的时候打了$n^2$的暴力,也想到了正解的优化,然而觉得它太麻烦了,而且$n^2$怎么优化也过不了50000啊,而且即使不优化前面30分我 ...

  8. laravel5.4 前后台未登陆,跳转到各自的页面

    https://www.imooc.com/wenda/detail/378208?t=266634 laravel我做了前后台登陆,后台未登录跳转到前台登陆页面了. 我想让后台未登入跳转到后台登陆页 ...

  9. hdu 3873 Invade the Mars(有限制的最短路 spfa+容器)

    Invade the Mars Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 365768/165536 K (Java/Others ...

  10. 高级PHP开发:利用PHPEMS搭建在线考试平台

    今天给大家分享一个小技巧,就是利用PHP ems搭建在线考试平台:希望能给你给予帮助: 在给大家分享之前,这里推荐下我自己建的PHP开发-VIP资料出售平台 :638965404,不管你是小白还是大牛 ...