令$f(a)_{i}=\min_{i<j\le n,a_{i}=a_{j}}j$​​(特别的,若不存在$j$​​则令$f(a)_{i}=n+1$​​),则有以下性质:

1.对于$b_{i}$​​​​​​​,存在$a_{i}$​​​​​​​使得$f(a)=b$​​​​,当且仅当$i<b_{i}$​​​​且不为$n+1$的$b_{i}$互不相同(以下称这样的$b_{i}$​​​​​​​合法)

2.合法的$b_{i}$​可以唯一确定$a_{i}$​​(仅关心权值是否相同,即$a_{i}\ne a'_{i}$当且仅当$\exists i\ne j,[a_{i}=a_{j}]\ne [a'_{i}=a'_{j}]$)

通过这两个性质,问题即判定是否存在合法的$b_{i}$,使得其(唯一)对应的$a_{i}$满足题中的条件

而题中的条件从$b_{i}$​​​的角度来看,实际上是这样的:令$\forall 1\le i<n,B_{i+1}=\max(B_{i},b_{i})$且$B_{1}$为最后一个之前没有出现过的数位置,也即$\max_{1\le i\le n且\forall 1\le j\le n,b_{j}\ne i}i$

考虑从后往前贪心确定$b_{i}$​​(其中$1\le i<n$​​),并维护以下两个集合:

1.$A_{0}$​​表示强制存在的元素(初始为$(B_{1},n]$​​​,若$b_{i}\in A_{0}$则将其从$A_{0}$​中删除)

2.$A_{1}$表示允许存在的元素(初始为$[1,B_{1})\cup\{n+1\}$,若$b_{i}\in A_{1}$且$b_{i}\le n$则将其从$A_{1}$中删除)

下面,再分类讨论:

1.若$B_{i}<B_{i+1}$​,则$b_{i}=B_{i+1}$​(注意判定$b_{i}>i$)

2.若$B_{i}=B_{i+1}$​,则要求$i<b_{i}\le B_{i}$​,注意到该区间的左端点单调递增,因此用set维护$A_{0}$​和$A_{1}$​,分别不断删除最小值(若删除$A_{0}$​的最小值则无解)直至最小值$>i$​​

进一步的,再分类讨论:

(1)若两者的最小值都不能选择,则无解(还有$\le B_{i}$​的限制)

(2)若只有一个最小值可以选择,显然选择该最小值即可

(3)若两个最小值都可以选择,设分别为$x$和$y$,将两者的都删除并将$\max(x,y)$加入$A_{1}$​

关于(3)的解释:注意到右端点单调不下降,因此最终$\min(x,y)$​能选择那么$\max(x,y)$​一定能选择

若$x<y$​​显然可以这样贪心,若$x>y$​​即要求$x=\max(x,y)$​​一定被选择,如果最终$x$​​被选择显然没有影响,若未被选择那么不妨将$b_{i}$​​修改为$x$​​​即可

(注意特判$B_{1}>n$的情况)

由此维护即可,时间复杂度为$o(n\log n)$,可以通过

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 set<int>A0,A1;
5 int t,n,B[N];
6 void del(int x){
7 if (x>n)return;
8 if (A0.find(x)!=A0.end())A0.erase(x);
9 else A1.erase(x);
10 }
11 int main(){
12 scanf("%d",&t);
13 while (t--){
14 scanf("%d",&n);
15 for(int i=1;i<=n;i++)scanf("%d",&B[i]);
16 bool flag=(B[1]>n);
17 for(int i=1;i<=n;i++)
18 if (B[i]<i){
19 flag=1;
20 break;
21 }
22 if (flag){
23 printf("NO\n");
24 continue;
25 }
26 A0.clear(),A1.clear();
27 for(int i=B[1]+1;i<=n;i++)A0.insert(i);
28 for(int i=1;i<B[1];i++)A1.insert(i);
29 A1.insert(n+1);
30 for(int i=1;i<n;i++){
31 if (B[i]<B[i+1])del(B[i+1]);
32 else{
33 if ((!A0.empty())&&((*A0.begin())<=i)){
34 flag=1;
35 break;
36 }
37 while ((*A1.begin())<=i)A1.erase(A1.begin());
38 int x=0,y=(*A1.begin());
39 if ((!A0.empty())&&((*A0.begin())<=B[i]))x=(*A0.begin());
40 if (y>B[i])y=0;
41 if ((!x)&&(!y)){
42 flag=1;
43 break;
44 }
45 if (x)del(x);
46 if (y)del(y);
47 if ((x)&&(y))A1.insert(max(x,y));
48 }
49 }
50 if (!A0.empty())flag=1;
51 if (flag)printf("NO\n");
52 else printf("YES\n");
53 }
54 return 0;
55 }

[hdu7034]Array的更多相关文章

  1. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  2. ES5对Array增强的9个API

    为了更方便的对Array进行操作,ES5规范在Array的原型上新增了9个方法,分别是forEach.filter.map.reduce.reduceRight.some.every.indexOf ...

  3. JavaScript Array对象

    介绍Js的Array 数组对象. 目录 1. 介绍:介绍 Array 数组对象的说明.定义方式以及属性. 2. 实例方法:介绍 Array 对象的实例方法:concat.every.filter.fo ...

  4. 了解PHP中的Array数组和foreach

    1. 了解数组 PHP 中的数组实际上是一个有序映射.映射是一种把 values 关联到 keys 的类型.详细的解释可参见:PHP.net中的Array数组    . 2.例子:一般的数组 这里,我 ...

  5. 关于面试题 Array.indexof() 方法的实现及思考

    这是我在面试大公司时碰到的一个笔试题,当时自己云里雾里的胡写了一番,回头也曾思考过,最终没实现也就不了了之了. 昨天看到有网友说面试中也碰到过这个问题,我就重新思考了这个问题的实现方法. 对于想进大公 ...

  6. javascript之活灵活现的Array

    前言 就如同标题一样,这篇文章将会灵活的运行Array对象的一些方法来实现看上去较复杂的应用. 大家都知道Array实例有这四个方法:push.pop.shift.unshift.大家也都知道 pus ...

  7. 5.2 Array类型的方法汇总

    所有对象都具有toString(),toLocaleString(),valueOf()方法. 1.数组转化为字符串 toString(),toLocaleString() ,数组调用这些方法,则返回 ...

  8. OpenGL ES: Array Texture初体验

    [TOC] Array Texture这个东西的意思是,一个纹理对象,可以存储不止一张图片信息,就是说是是一个数组,每个元素都是一张图片.这样免了频繁地去切换当前需要bind的纹理,而且可以节省系统资 ...

  9. Merge Sorted Array

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note:Yo ...

随机推荐

  1. Java程序的执行过程

    Java程序的执行过程 编译器将 Java 源代码编译成字节码class文件 类加载到 JVM 里面后,执行引擎把字节码转为可执行代码 执行的过程,再把可执行代码转为机器码,由底层的操作系统完成执行

  2. VirtualBox设置双网卡实现主宿互访及虚拟机访问互联网总结

    1,配置网络 注:VirtualBox要在全局工具-主机网络管理器里新建一个虚拟网卡. 然后虚拟机的网卡1设置为host-only,界面名称为新建的虚拟网卡(我这里为了不跟主机ip冲突,设置成了不同网 ...

  3. IO之字符流

    什么是字符流 对于文本文件(.txt .java .c .cpp) 使用字符流处理 注意点 读入的文件一定要存在 否则就会报FileNotFoundException 异常的处理 为了保证流资源 一定 ...

  4. Task 异步小技巧

    原文地址:Task 异步小技巧 - 一事冇诚 - 博客园 (cnblogs.com) async Task 语法糖出来后,异步编程变得非常简单,适合需要耗费较长时间的任务. 有些小伙伴使用后可能会非常 ...

  5. 从C过渡到C++需要了解的“新特性”

    第一个C++程序 #include <iostream> using namespace std; //编译指令 int main() { cout << "Hell ...

  6. python收集参数与解包

    收集任意数量的实参 def make_pizza(*toppings): """打印顾客点的所有配料""" print(toppings) ...

  7. 远程设备管理opendx平台搭建-appium和adb的安装

    多年不见了,说起来也有3年了我又开始写博客了,这几年我还是没啥长进,还是干测试,但是测试行业的话,我已经成了一个测开了,也在搭建自己的测试网站 本系列文章讲述的是一个系列的第一部分,最终可以搭建一整套 ...

  8. the Agiles Scrum Meeting 7

    会议时间:2020.4.15 21:00 1.每个人的工作 根据项目进度,我们将原先的完善组和debug组合并,成为团队项目增量开发组,原增量组成为个人结对项目增量开发组. 今天已完成的工作 个人结对 ...

  9. 一张图彻底搞懂Spring循环依赖

    1 什么是循环依赖? 如下图所示: BeanA类依赖了BeanB类,同时BeanB类又依赖了BeanA类.这种依赖关系形成了一个闭环,我们把这种依赖关系就称之为循环依赖.同理,再如下图的情况: 上图中 ...

  10. CPU使用率和平均负载

    转载: https://mp.weixin.qq.com/s?__biz=MzU4NzU0MDIzOQ==&mid=2247487782&idx=3&sn=3f04bb053d ...