题目链接:https://nanti.jisuanke.com/t/28412

题意:

  给出n个数的序列。问序列中有多少个区间满足,排序完之后任意两个相邻的数之差不大于1。

题解:

  用max表示区间最大值,min表示区间最小值,cnt表示区间数字的种数。那么问题转化成求max-min=cnt+1的区间数。

  用线段树维护每个区间的max-min-cnt最小值及最小值的个数,不用单独维护max,min和cnt。注意max-min >= cnt+1.

  从1~n枚举R。对于每个枚举的R,更新以R为后缀的[L,R]区间的max-min-cnt值。

  对于max和min可以用单调栈维护,max和min对max-min-cnt的贡献采用区间加减的形式而不是区间覆盖。

  对于cnt可以用一个vis[]数组维护上一次的出现位置,然后也进行区间加减。数据是1e9的,vis[]数组可以离散一下或者用map代替。

  最后对于每一个枚举的R,统计max-min-cnt的值为-1的[L,R]数。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e5+;
  4. typedef long long ll;
  5. int t, n, k;
  6. int nx, nn;
  7. int lzy[N*], sum[N*], val[N*];
  8. ll ans;
  9. map<int, int> m;
  10. struct node {
  11. int p, w;
  12. node() {}
  13. node(int a, int b) {
  14. p = a; w = b;
  15. }
  16. }mx[N], mn[N];
  17. void push_up(int id) {
  18. val[id] = min(val[id<<], val[id<<|]);
  19. if(val[id<<] == val[id<<|]) sum[id] = sum[id<<]+sum[id<<|];
  20. else if(val[id<<] < val[id<<|]) sum[id] = sum[id<<];
  21. else sum[id] = sum[id<<|];
  22. }
  23. void push_down(int id) {
  24. lzy[id<<] += lzy[id];
  25. lzy[id<<|] += lzy[id];
  26. val[id<<] += lzy[id];
  27. val[id<<|] += lzy[id];
  28. lzy[id] = ;
  29. }
  30. void insert(int id, int l, int r, int p) {
  31. if(l == r) {
  32. val[id] = -;
  33. sum[id] = ;
  34. return ;
  35. }
  36. if(lzy[id]) push_down(id);
  37. int mid = l+r>>;
  38. if(p<=mid) insert(id<<, l, mid, p);
  39. else insert(id<<|, mid+, r, p);
  40. push_up(id);
  41. }
  42. void update(int id, int l, int r, int ql, int qr, int v) {
  43. if(ql<=l && r<=qr) {
  44. lzy[id] += v;
  45. val[id] += v;
  46. return ;
  47. }
  48. if(lzy[id]) push_down(id);
  49. int mid = l+r>>;
  50. if(ql<=mid) update(id<<, l, mid, ql, qr, v);
  51. if(qr>mid) update(id<<|, mid+, r, ql, qr, v);
  52. push_up(id);
  53. }
  54. int main() {
  55. scanf("%d", &t);
  56. for(int casee = ; casee <= t; casee++) {
  57. ans = nx = nn = ;
  58. m.clear();
  59. scanf("%d", &n);
  60. memset(lzy, , sizeof(int)*(*n+));
  61. memset(sum, , sizeof(int)*(*n+));
  62. memset(val, 0x3f3f3f3f, sizeof(int)*(*n+));
  63. for(int i = ; i <= n; i++) {
  64. scanf("%d", &k);
  65. insert(, , n, i);
  66. int p = i, v;
  67. while(nx > && mx[nx].w <= k) {
  68. p = mx[nx].p, v = k-mx[nx].w;
  69. nx--;
  70. update(, , n, mx[nx].p+, p, v);
  71. }
  72. mx[++nx] = node(i, k);
  73. p = i;
  74. while(nn > && mn[nn].w >= k) {
  75. p = mn[nn].p, v = k-mn[nn].w;
  76. nn--;
  77. update(, , n, mn[nn].p+, p, -v);
  78. }
  79. mn[++nn] = node(i, k);
  80. int l;
  81. if(m.find(k) != m.end()) l = m[k]+;
  82. else l = ;
  83. if(l <= i-) update(, , n, l, i-, -);
  84. m[k] = i;
  85. ans += sum[];
  86. }
  87. printf("Case #%d: %lld\n", casee, ans);
  88. }
  89. }

2018宁夏邀请赛L Continuous Intervals的更多相关文章

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

    2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树) 传送门:https://nanti.jisuanke.com/t/41296 题意: 给一个数列A 问在数列A中有多 ...

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

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

  3. “2018宁夏邀请赛 ” 兼 “The 2019 Asia Yinchuan First Round Online Programming”

    ------------7题弟弟,被各位半小时13题的大佬打惨了(滑稽)---------- 签到题就不写了. F :Moving On            (1247ms) 题意:给定大小为N的带 ...

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

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

  5. 2018宁夏邀请赛网赛 I. Reversion Count(java练习题)

    题目链接 :https://nanti.jisuanke.com/t/26217 Description: There is a positive integer X, X's reversion c ...

  6. 2018宁夏邀请赛K Vertex Covers

    题目链接:https://nanti.jisuanke.com/t/28411 题意: 给出n(n<=36)个点的一个图.求点覆盖集数. 题解: 将n个点折半为L和R两部分.对于R内部的边,枚举 ...

  7. 2018宁夏邀请赛G(DFS,动态规划【VECTOR<PAIR>】)

    //代码跑的很慢四秒会超时,结尾附两秒代码(标程) #include<bits/stdc++.h>using namespace std;typedef long long ll;cons ...

  8. 2018宁夏邀请赛K题Vertex Covers(高维前缀和 状压 折半

    https://vjudge.net/problem/Gym-102222K 题意:给定N点M边的无向图,每个点有点权.  点覆盖表示某个点集S{}覆盖了所有的边,其贡献是S中点权之积. 现在让你求所 ...

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

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

随机推荐

  1. 实现php Curl 调用不同项目中方法

    之前为了实现跨项目调用方法,遇到的一些问题和解决方法总结. 话不多说,直接复制代码先跑了再说! jq代码. $.ajax({ type: "post", dataType: &qu ...

  2. 【shell脚本学习-4】

    文本处理 #!/bin/bash#----------文本处理---------- #---------------echo----------------- # "-n":处理光 ...

  3. Java源码解析——集合框架(二)——ArrayBlockingQueue

    ArrayBlockingQueue源码解析 ArrayBlockingQueue是一个阻塞式的队列,继承自AbstractBlockingQueue,间接的实现了Queue接口和Collection ...

  4. 让UltraEdit-32成为Delphi 7编译器的工具设置

    UltraEdit-32编译Delphi的工具设置 {================================================}Dcc32 命令行(&C):C:\Pro ...

  5. Qt之pro文件解析

    在我们创建Qt工程项目时,Qt Creator总会创建一个.pro文件,我们称.pro文件为Qt的工程管理文件.一个工程项目可以包含一个或多个.pro文件.理解和掌握pro文件的用法,将有利于Qt开发 ...

  6. SET UPDATE TASK LOCAL (ローカル更新 )

    ローカル更新では.更新プログラムは要求を処理したのと同じワークプロセスによって実行されます.ダイアログユーザは更新が終了するまで待ってから追加データを入力しなければなりません.データベースへのアクセス ...

  7. C++11中std::forward的使用

    std::forward argument: Returns an rvalue reference to arg if arg is not an lvalue reference; If arg ...

  8. redis学习资料汇总

    redis学习资料汇总 2017年01月07日 22:10:37 阅读数:281 转载:http://blog.csdn.net/wtyvhreal/article/details/50427627 ...

  9. Unity 3d C#和Javascript脚本互相调用 解决方案(非原创、整理资料,并经过实践得来)

    Unity 3d C#和Javascript脚本互相调用 解决方案 1.背景知识 脚本的编译过程分四步: 1. 编译所有 ”Standard Assets”, “Pro Standard Assets ...

  10. Spring.Net在ASP.NET Mvc里使用的一个小例子

    就贴个小例子,就不注意格式了. 1.下载dll NuGet的下载地址:http://docs.nuget.org/docs/start-here/installing-nuget 在vs的NuGet里 ...