Diverse Segments


1.前言

气运不好,一拿手就想错了方向,然后就写得特别复杂……

神奇 DJ 调码真厉害 (((舔

2.题解

首先想暴力,考虑一个区间 [ l , r ] [l, r] [l,r],记值为 v a l val val 的元素为 p : p 1 , p 2 . . . p k p: p_1, p_2 ... p_k p:p1​,p2​...pk​。

那么由于我们可以修改的区间是连续的,所以 p 2 . . . p k − 1 p_2 ... p_{k - 1} p2​...pk−1​ 这些元素一定会被框入我们的答案区间,把这些点剔除后就只剩下 p 1 , p k p_1, p_k p1​,pk​,所以答案区间只需要包含 p 1 p_1 p1​ 或 p n p_n pn​ 即可。

那么记这些被剔除的点的编号值域为 [ l , r ] [l, r] [l,r],那么答案区间 [ L , R ] [L, R] [L,R] 必须满足 L < l , R > r L < l, R > r L<l,R>r。

还有一种情况,就是没有被剔除的点或者相同的两个元素都处于 [ 1 , L − 1 ] [1, L - 1] [1,L−1] 或 [ R + 1 , n ] [R + 1, n] [R+1,n]。

这种情况特判即可,那么 R R R 必须要大于这两个元素下标的最小值。

接下来分别将剩下的两个难点:

  1. 求得 [ l , r ] [l, r] [l,r]
  2. 判断选择 p 1 p_1 p1​ 还是 p n p_n pn​

第一个难点

枚举 i i i,表示给 a [ i ] a[i] a[i] 找值相同的最远的点(当然得都在某个给定区间)。

那么我们只需求出 max ⁡ ( r j ) ( l j ≤ i ) \max (r_j) (l_j \leq i) max(rj​)(lj​≤i),我们发现可以给区间按左端点为第一关键字从小到大排序,然后双指针,求出最远的区间右端点后在这个区间内寻找到第二靠左的和第二靠右的点即可。


第二个难点

和第一个难点类似的思路,从小到大( [ 1 , l ] [1, l] [1,l])枚举 L L L,然后发现如果错过了某个 p 1 p_1 p1​,那么就需要 R ≥ p n R \geq p_n R≥pn​ 了(对头已经一定不在区间里,那么队尾一定要在区间里),与 p n p_n pn​ 比个 max ⁡ \max max 即可。


3.参考代码

#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define fi first
#define se second
#define db double
#define LL long long
//#define int long long
#define PII pair <int, int>
#define ULL unsigned long long
#define MP(x,y) make_pair (x, y)
#define rep(i,j,k) for (int i = (j); i <= (k); i++)
#define per(i,j,k) for (int i = (j); i >= (k); i--)template <typename T>
void read (T &x) {x = 0; T f = 1; char ch = getchar ();while (ch < '0' || ch > '9') {if (ch == '-') f = -1;ch = getchar ();}while (ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + ch - '0';ch = getchar ();}x *= f;
}
template <typename T, typename... Args>
void read (T &x, Args&... Arg) {read (x), read (Arg...);
}
const int MaxPrint = 1000;
int Poi_For_Print, Tmp_For_Print[MaxPrint + 5];
template <typename T>
void write (T x) {if (x == 0) {putchar ('0');return;}bool flag = (x < 0 ? 1 : 0);x = (x < 0 ? -x : x);while (x) Tmp_For_Print[++Poi_For_Print] = x % 10, x /= 10;if (flag) putchar ('-');while (Poi_For_Print) putchar (Tmp_For_Print[Poi_For_Print--] + '0');
}
template <typename T, typename... Args>
void write (T x, Args... Arg) {write (x); putchar (' '); write (Arg...);
}
template <typename T, typename... Args>
void print (T x, char ch) {write (x); putchar (ch);
}
template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }const int Maxn = 2 * 1e5;
const int Inf = 0x3f3f3f3f;int t, n, m;
int a[Maxn + 5], cnt;
PII b[Maxn + 5], c[Maxn + 5];
set <int> bak[Maxn + 5];vector <int> lsh;
int Find (int x) { return lower_bound (lsh.begin (), lsh.end (), x) - lsh.begin () + 1; }signed main () {//     freopen ("C:\\Users\\Administrator\\Desktop\\lihan\\1.in", "r", stdin);
//    freopen ("C:\\Users\\Administrator\\Desktop\\lihan\\1.out", "w", stdout);read (t);while (t--) {read (n, m);lsh.clear ();rep (i, 1, n) bak[i].clear ();rep (i, 1, n)read (a[i]), lsh.push_back (a[i]);sort (lsh.begin (), lsh.end ()); lsh.erase (unique (lsh.begin (), lsh.end ()), lsh.end ());rep (i, 1, n)a[i] = Find (a[i]), bak[a[i]].insert (i);rep (i, 1, m)read (b[i].fi, b[i].se);sort (b + 1, b + 1 + m);int poi = 0, _max = -Inf;int l = n, r = 0;rep (i, 1, n) {//求出 [l, r] while (poi + 1 <= m && b[poi + 1].fi <= i) // b[poi + 1] 询问区间的最短点囊括了 i _max = Max (_max, b[++poi].se);if (_max < i) {continue;}auto pl = bak[a[i]].lower_bound (i), pr = bak[a[i]].upper_bound (_max);if (pr == bak[a[i]].begin ()) continue;pr--;if (pl == bak[a[i]].end ()) continue;if (pr == bak[a[i]].begin ()) continue;pl++, pr--; // 选出第二大和第二小的编号 if (pl == bak[a[i]].end ()) continue;if (*pl <= *pr) l = Min (l, *pl), r = Max (r, *pr);}poi = 0, _max = -Inf;int Now_Max = r, res = Inf; // Now_Max 即为 R rep (i, 1, n) {//特判分居 [l, r] 的同一侧的情况 while (poi + 1 <= m && b[poi + 1].fi <= i)_max = Max (_max, b[++poi].se);if (_max < i) {continue;}auto pl = bak[a[i]].lower_bound (i), pr = bak[a[i]].upper_bound (_max);if (pl == bak[a[i]].end ()) continue;if (pr == bak[a[i]].begin ()) continue;pr--;if (*pl < *pr && (*pr <= l || *pl >= r)) l = Min (l, *pr), Now_Max = Max (Now_Max, *pl);}poi = 0, _max = -Inf;rep (i, 1, l) {//枚举 L while (poi + 1 <= m && b[poi + 1].fi < i) _max = Max (_max, b[++poi].se);if (_max < i) {res = Min (res, Now_Max - i + 1);continue;}if (i == 1) {res = Min (res, Now_Max - i + 1);continue;}auto pl = bak[a[i - 1]].lower_bound (i), pr = bak[a[i - 1]].upper_bound (_max); //现在与头 a[i - 1] 错过 if (pl == bak[a[i - 1]].end ()) {//求出 p[n] res = Min (res, Now_Max - i + 1);continue;}if (pr == bak[a[i - 1]].begin ()) {res = Min (res, Now_Max - i + 1);continue;}pr--;if (*pl <= *pr) Now_Max = Max (Now_Max, *pr);res = Min (res, Now_Max - i + 1);}print (Max (res, 0), '\n');}return 0;
}

Diverse Segments 全网最抽风做法相关推荐

  1. Distance Tree 全网最丑做法

    1.前言 为什么我总是一些正常人想不到的思路-- 2.题解 首先有一个很显然的结论,连接的两个点一个为根节点,一个为以一为链顶的最长链上,记这个最长链的点集合为 l l l. 假设我们当前连边的长度为 ...

  2. CF125E MST company (凸优化+MST)

    qwq自闭的一个题 我来修锅辣!!!!!! 这篇题解!可以\(hack\)全网大部分的做法!!! 首先,我们可以把原图中的边,分成两类,一类是与\(1\)相连,另一类是不与\(1\)相连. 原题就转化 ...

  3. Cloudera Manager集群(CDH6.2.0.1)完整搭建指南

    目录 引子 下载所有安装包准备离线安装 大数据安装前的环境规划 基础环境准备 host名与ip绑定 各主机间设成免密登录 安装openjdk 各节点间关selinux关firewalld 然后使用以下 ...

  4. 区块链革命:从《失控》说起

    <失控:全人类的最终命运和结局>是著名作家凯文·凯利写于20世纪90年代初,关于自然万物.人类社会和 科学技术如何进化的著作.彼时,互联网标准协议在经过长达近三十年的实验和争议后,刚刚被确 ...

  5. 读《区块链革命 》有感

    [引言] 读<失控:全人类的最终命运和结局>有感. <失控:全人类的最终命运和结局>是著名作家凯文·凯利写于20世纪90年代初,关于自然万物.人类社会和科学技术如何进化的著作. ...

  6. Attention Mechanism[Transformer、Transformer-XL、XLNet]

    Content Attention Mechanism--->聚焦关键点 1 History 2 Introduction 3 structure 4 application situation ...

  7. 每天总有那么几分钟脑子抽风-记录一下一个奇葩的游戏公司做法

    碰过不少奇葩的游戏公司 一.老板卖水果赚钱了,投钱开的游戏公司 二.二老板闲着没事,投个10W/月开个游戏公司(其实10W不少了...要是20年前) 三.做互联网研发的,觉得游戏不也是研发吗,转行做游 ...

  8. 全网最详细的大数据集群环境下如何正确安装并配置多个不同版本的Cloudera Hue(图文详解)...

    不多说,直接上干货! 为什么要写这么一篇博文呢? 是因为啊,对于Hue不同版本之间,其实,差异还是相对来说有点大的,具体,大家在使用的时候亲身体会就知道了,比如一些提示和界面. 全网最详细的大数据集群 ...

  9. Codeforces1080F. Katya and Segments Sets

    Codeforces1080F. Katya and Segments Sets 题意:给定n个集合,每个集合里有一些区间\([l_i,r_i]\),有m次询问,每次询问区间\([x,y]\)中,是否 ...

最新文章

  1. nodejs express 加载html模板
  2. Codevs 3134 Circle
  3. select()函数用法
  4. linux 环境下配置ftp服务器
  5. 深度学习之基于CNN实现汉字版手写数字识别(Chinese-Mnist)
  6. ST函数(ST表)RMQ O(1)查询 离线
  7. 虚拟机和linux的安装
  8. JavaSE简单实现多线程聊天
  9. 洛谷 P1656 炸铁路
  10. 运维工具 Ansible 快速入门教程
  11. python 内存溢出_python之记录一次内存溢出
  12. 基于C#的图片浏览及显示功能(源码)
  13. mysqllinux操作,万字解析!
  14. HDU 6411 带劲的and和
  15. SQL SERVER查询生僻字问题
  16. jQuery Mobel 学习相关资料整理(一)
  17. mysql binlog event_MySQL binlog中的事件类型详解
  18. Java入门篇——零基础如何学习Java
  19. 当动作捕捉应用到教学教研工作领域
  20. 油烟净化器电场可以使用洗衣粉来清洗吗?

热门文章

  1. 简单实现x的n次方(10 分)
  2. Android Studio之Fragment界面切换总结
  3. js 获取本月、本周、本年年初
  4. 关于时间复杂度的几个典型证明
  5. JMS规范和AMQP协议
  6. jsp页面跳转以及后台跳转
  7. 【转】Oracle在线重定义DBMS_REDEFINITION 普通表—分区表
  8. MacBook 往服务器上传、下载文件的几种操作
  9. 个人永久性免费-Excel催化剂功能第17波-批量文件改名、下载、文件夹创建等
  10. 绩效考核不等同于绩效管理