题意

给定长度为\(n\)的数组\(a\),其中任意\(a_i \leq x\)

定义\(f(l,r)\)为删除\(a\)中值域在\([l,r]\)的数后剩余的数组.

统计满足\(1\leq l \leq r \leq x\)且\(f(l,r)\)是非严格不下降序列的数对\((l,r)\)的数量。

题解

首先想想就可以发现这个\(l\)和\(r\)是有单调性的。那思路就可以往双指针/二分那边靠一下。

现在的问题就是怎么做到\(O(1)\)或者\(O(\log n)\) 判断删除一段区间后的序列是否合法。

把最后的序列拆成两段:权值在\((1,l-1)\)和权值在\((r+1,x)\)的。

发现只需要\((1,l-1)\)这段满足按权值排序后下标单调上升,\((r+1,x)\)这段同理,并且\(l-1\)的下标比\(r+1\)的下标小。

那么这个东西其实是可以预处理出来的。

考虑处理出\(posmax\)和\(posmin\)表示数字\(i\)出现的最小下标和最大下标,\(premax\)和\(sufmin\)表示按权值排序后\(1-i\)的最大下标 和 按权值排序后\(i-x\)的最小下标。

依靠上面预处理出来的数据我们就可以再处理出一个\(precan\)和\(sufcan\)表示\((1,i)\)是否合法以及\((i,x)\)是否合法,那么就可以\(O(1)\)判断删除一段区间后的序列是否合法了。

使用双指针就可以做到\(O(n)\)解决。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. namespace io {
  4. char buf[1<<21], *p1 = buf, *p2 = buf;
  5. inline char gc() {
  6. if(p1 != p2) return *p1++;
  7. p1 = buf;
  8. p2 = p1 + fread(buf, 1, 1 << 21, stdin);
  9. return p1 == p2 ? EOF : *p1++;
  10. }
  11. #define G gc
  12. #ifndef ONLINE_JUDGE
  13. #undef G
  14. #define G getchar
  15. #endif
  16. template<class I>
  17. inline void read(I &x) {
  18. x = 0; I f = 1; char c = G();
  19. while(c < '0' || c > '9') {if(c == '-') f = -1; c = G(); }
  20. while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = G(); }
  21. x *= f;
  22. }
  23. template<class I>
  24. inline void write(I x) {
  25. if(x == 0) {putchar('0'); return;}
  26. I tmp = x > 0 ? x : -x;
  27. if(x < 0) putchar('-');
  28. int cnt = 0;
  29. while(tmp > 0) {
  30. buf[cnt++] = tmp % 10 + '0';
  31. tmp /= 10;
  32. }
  33. while(cnt > 0) putchar(buf[--cnt]);
  34. }
  35. #define in(x) read(x)
  36. #define outn(x) write(x), putchar('\n')
  37. #define out(x) write(x), putchar(' ')
  38. } using namespace io;
  39. #define ll long long
  40. const int N = 1000100;
  41. const int inf = 1e9;
  42. int n, x;
  43. int a[N];
  44. int posmn[N], posmx[N];
  45. //每个大小的数的最左端点和最右端点
  46. int sufmn[N], premx[N];
  47. //从大到小/从小到大的max和min位置
  48. bool sufcan[N], precan[N];
  49. //保留i到x这段是否合法,保留1到i这段是否合法
  50. bool check(int l, int r) {
  51. if(!precan[l - 1]) return false;
  52. if(!sufcan[r + 1]) return false;
  53. if(sufmn[r + 1] < premx[l - 1]) return false;
  54. return true;
  55. }
  56. int main() {
  57. read(n); read(x);
  58. memset(posmn, 0x3f, sizeof(posmn));
  59. for(int i = 1; i <= n; ++i) read(a[i]);
  60. for(int i = 1; i <= n; ++i) {
  61. posmn[a[i]] = min(posmn[a[i]], i);
  62. posmx[a[i]] = max(posmx[a[i]], i);
  63. }
  64. sufmn[x + 1] = inf;
  65. for(int i = 1; i <= x; ++i) premx[i] = max(premx[i - 1], posmx[i]);
  66. for(int i = x; i; --i) sufmn[i] = min(sufmn[i + 1], posmn[i]);
  67. sufcan[x + 1] = precan[0] = true;
  68. for(int i = 1; i <= x; ++i) precan[i] = precan[i - 1] && (premx[i - 1] < posmn[i]);
  69. for(int i = x; i; --i) sufcan[i] = sufcan[i + 1] && (posmx[i] < sufmn[i + 1]);
  70. ll sum = 0;
  71. int l = 1, r = 1;
  72. for(; l <= x; ++l) {
  73. if(l > r) ++r;
  74. while(r < x && !check(l, r)) ++r;
  75. if(check(l, r)) sum += x - r + 1;
  76. }
  77. outn(sum);
  78. return 0;
  79. }

CF1167E. Range Deleting的更多相关文章

  1. Codeforces 1167 E Range Deleting 双指针+思维

    题意 给一个数列\(a​\),定义\(f(l,r)​\)为删除\(a​\)中所有满足\(l<=a_i<=r​\)的数后的数列,问有多少对\((l,r)​\),使\(f(l,r)​\)是一个 ...

  2. Educational Codeforces Round 65 (Rated for Div. 2) E. Range Deleting(思维+coding)

    传送门 参考资料: [1]:https://blog.csdn.net/weixin_43262291/article/details/90271693 题意: 给你一个包含 n 个数的序列 a,并且 ...

  3. 1167E - Range Deleting 双指针

    题意:给出n个数的序列,并给出x,这n个数的范围为[1,x],f(L,R)表示删除序列中取值为[l,r]的数,问有几对L,R使得操作后的序列为非递减序列 思路:若[l,r]成立,那么[l,r+1],. ...

  4. Educational Codeforces Round 65 (Rated for Div. 2)题解

    Educational Codeforces Round 65 (Rated for Div. 2)题解 题目链接 A. Telephone Number 水题,代码如下: Code #include ...

  5. [ Educational Codeforces Round 65 (Rated for Div. 2)][二分]

    https://codeforc.es/contest/1167/problem/E E. Range Deleting time limit per test 2 seconds memory li ...

  6. codeforces Educational Codeforces Round 65 (补完)

    C News Distribution 并查集水题 D Bicolored RBS 括号匹配问题,如果给出的括号序列nesting depth为n,那么最终可以分成两个nesting depth为n ...

  7. Educational Codeforces Round 65 E,F

    E. Range Deleting 题意:给出一个序列,定义一个操作f(x,y)为删除序列中所有在[x,y]区间内的数.问能使剩下的数单调不减的操作f(x,y)的方案数是多少. 解法:不会做,思维跟不 ...

  8. Educational Codeforces Round 65 选做

    好久没更博客了,随便水一篇 E. Range Deleting 题意 给你一个长度为 \(n\) 的序列 \(a_1,a_2,\dots a_n\) ,定义 \(f(l,r)\) 为删除 \(l\le ...

  9. Codeforces Edu Round 65 A-E

    A. Telephone Number 跟之前有一道必胜策略是一样的,\(n - 10\)位之前的数存在\(8\)即可. #include <iostream> #include < ...

随机推荐

  1. GIT 基础 &本地服务器搭建

    Git是一款免费.开源的分布式版本控制系统.众所周知的Github便是基于Git的开源代码库以及版本控制系统,由于其远程托管服务仅对开源免费,所以搭建本地Git服务器也是个较好的选择,本文将对此进行详 ...

  2. LeetCode 537. 复数乘法(Complex Number Multiplication)

    537. 复数乘法 537. Complex Number Multiplication 题目描述 Given two strings representing two complex numbers ...

  3. python类型检测最终指南--Typing模块的使用

    正文共:30429 字 预计阅读时间:76分钟 原文链接:https://realpython.com/python-type-checking/ 作者:Geir Arne Hjelle 译者:陈祥安 ...

  4. 《TCP/IP - TCP/UDP》

    一:概述 - 由于 IP 的传输是无状态的,IP 提供尽力服务,但并不保证数据可以到达主机. - 所以,数据的完整性需要更上层的 传输层来保证.TCP和UDP 均属于 传输层. 二:UDP - 特点 ...

  5. STL源码剖析——Iterators与Traits编程#5 __type_traits

    上节给出了iterator_traits以及用到traits机制的部分函数的完整代码,可以看到traits机制能够提取迭代器的特性从而调用不同的函数,实现效率的最大化.显然这么好的机制不应该仅局限于在 ...

  6. PHP提取中英文首字母的方法(首字母索引)

    function Getzimu($str) { $str= iconv("UTF-8","gb2312", $str);//如果程序是gbk的,此行就要注释掉 ...

  7. python学习-69 包装和授权

    包装 1.二次加工标准类型(包装) class List(list): def append(self, a_objcet): if type(a_objcet) is str: super().ap ...

  8. 【微信小程序学习笔记】入门与了解

    [微信小程序学习笔记(一)] IDE 下载安装 下载地址 官方工具:https://mp.weixin.qq.com/debug/w … tml?t=1476434678461 下载可执行文件后,可按 ...

  9. cocos版本说明

    一直知道cocos是做游戏的,想学习一下,结果去官网一看就懵逼了.Cocos Creator,Cocos2d-x,cocos studio,Cocos2d-js,Cocos2d-x-lua,那一种才是 ...

  10. postman调用webapi错误记录

    1.webapi ,接口中header中,value 不能太长,太长会报错 结局:value中不要存太长的数据 2.如果key 中有中文,会获取不到数据 , 解决:需要把中文转码,然后后端解码 3.如 ...