题意

给定长度为\(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)\)解决。

#include <bits/stdc++.h>
using namespace std; namespace io {
char buf[1<<21], *p1 = buf, *p2 = buf;
inline char gc() {
if(p1 != p2) return *p1++;
p1 = buf;
p2 = p1 + fread(buf, 1, 1 << 21, stdin);
return p1 == p2 ? EOF : *p1++;
}
#define G gc #ifndef ONLINE_JUDGE
#undef G
#define G getchar
#endif template<class I>
inline void read(I &x) {
x = 0; I f = 1; char c = G();
while(c < '0' || c > '9') {if(c == '-') f = -1; c = G(); }
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = G(); }
x *= f;
} template<class I>
inline void write(I x) {
if(x == 0) {putchar('0'); return;}
I tmp = x > 0 ? x : -x;
if(x < 0) putchar('-');
int cnt = 0;
while(tmp > 0) {
buf[cnt++] = tmp % 10 + '0';
tmp /= 10;
}
while(cnt > 0) putchar(buf[--cnt]);
} #define in(x) read(x)
#define outn(x) write(x), putchar('\n')
#define out(x) write(x), putchar(' ') } using namespace io; #define ll long long
const int N = 1000100;
const int inf = 1e9; int n, x;
int a[N]; int posmn[N], posmx[N];
//每个大小的数的最左端点和最右端点
int sufmn[N], premx[N];
//从大到小/从小到大的max和min位置
bool sufcan[N], precan[N];
//保留i到x这段是否合法,保留1到i这段是否合法 bool check(int l, int r) {
if(!precan[l - 1]) return false;
if(!sufcan[r + 1]) return false;
if(sufmn[r + 1] < premx[l - 1]) return false;
return true;
} int main() {
read(n); read(x);
memset(posmn, 0x3f, sizeof(posmn));
for(int i = 1; i <= n; ++i) read(a[i]); for(int i = 1; i <= n; ++i) {
posmn[a[i]] = min(posmn[a[i]], i);
posmx[a[i]] = max(posmx[a[i]], i);
}
sufmn[x + 1] = inf;
for(int i = 1; i <= x; ++i) premx[i] = max(premx[i - 1], posmx[i]);
for(int i = x; i; --i) sufmn[i] = min(sufmn[i + 1], posmn[i]);
sufcan[x + 1] = precan[0] = true;
for(int i = 1; i <= x; ++i) precan[i] = precan[i - 1] && (premx[i - 1] < posmn[i]);
for(int i = x; i; --i) sufcan[i] = sufcan[i + 1] && (posmx[i] < sufmn[i + 1]); ll sum = 0;
int l = 1, r = 1;
for(; l <= x; ++l) {
if(l > r) ++r;
while(r < x && !check(l, r)) ++r;
if(check(l, r)) sum += x - r + 1;
} outn(sum);
return 0;
}

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. 【视频开发】RTSP SERVER(基于live555)详细设计

    /* *本文基于LIVE555的嵌入式的RTSP流媒体服务器一个设计文档,个中细节现剖于此,有需者可参考指正,同时也方便后期自己查阅.(本版本是基于2011年的live555) 作者:llf_17@q ...

  2. 记录一次使用iisnode部署node项目遇到的坑!

    前言:最近因为项目原因,需要在IIS下部署node项目,在此之前,曾经部署过类似的项目,因此在这次部署还算比较顺利,只是在其中遇到了几个比较坑的问题,所以这次使用博客记录下来,如有园友遇到过类似问题, ...

  3. IDEA一个工程如何启动多次

  4. 如何在运行时更改JMeter的负载

    在某些情况下,能够在不停止测试的情况下更改性能测试产生的负载是有用的或必要的.这可以通过使用Apache JMeter™的恒定吞吐量计时器和Beanshell服务器来完成.在这篇文章中,我们将介绍如何 ...

  5. JavaWeb实现增删查改(图书信息管理)之删除功能实现

    —————————————————————————————————————————————————————————— 删除按钮对应的servlet -->DeleteBooks.java  ↓ ...

  6. jQuery实现简单导航栏的样式切换

    style css样式部分: ul{ margin: 0 auto; height: 50px; background-color: #369;} ul>li{ text-decoration: ...

  7. class——python编程从入门到实践

    创建和使用类 1. 创建Dog类 class Dog: """一次模拟小狗的简单尝试""" def __init__(self, name, ...

  8. AVR单片机教程——按键状态

    好久没更新了,今天开始继续,争取日更. 今天我们来讲按键.开发板的右下角有4个按键,按下会有明显的“咔嗒”声.如何检测按键是否被按下呢?首先要把按键或直接或间接地连接到单片机上.与之前使用的4个LED ...

  9. kafka和zookeeper安装部署(版本弄不好就是坑)

    yum install -y unzip zip 配置host vi /etc/host172.19.68.10 zk1 1. zookeeper zookeeper下载地址 http://mirro ...

  10. Springboot 之 静态资源路径配置

    1.静态资源路径是指系统可以直接访问的路径,且路径下的所有文件均可被用户通过浏览器直接读取. 2.在Springboot中默认的静态资源路径有:classpath:/META-INF/resource ...