令$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. keepalived-master-slave

    Master配置 global_defs { notification_email { root@localhost } notification_email_from keeplived@local ...

  2. sprintboot整合mybatis查询不出数据

    数据库有数据,程序没有任何报错,但是查询结果没有数据,list显示[null,nul]. 检查了sql语句,以及controller.service.mapper,检查没发现问题,怀疑是字段映射问题. ...

  3. LDAP-初见

    目录 什么是LDAP? LDAP 协议能解决什么问题? Spring Boot中使用LDAP来统一管理用户信息 添加用户 连接LDAP服务端 什么是LDAP? LDAP 的全称是 Lightweigh ...

  4. Java多线程中的死锁

    Java多线程中的死锁 死锁产生的原因 线程死锁是指由两个以上的线程互相持有对方所需要的资源,导致线程处于等待状态,无法往前执行. 当线程进入对象的synchronized代码块时,便占有了资源,直到 ...

  5. Java:抽象类和接口小记

    Java:抽象类和接口小记 对 Java 中的 抽象类和接口,做一个微不足道的小小小小记 抽象类:使用 abstract 修饰,子类用 extends 继承: 接口:使用 interface 修饰,采 ...

  6. activiti流程图上获取各节点的信息获取

    背景:         由于项目的需要,当用户在查看流程图时,当点击某个流程图片上的节点时,需要提示一些信息,这就需要获取各个节点的信息,此处获取id和name的值.           注意:这个并 ...

  7. elasticsearch的dsl查询

    测试es的dsl查询,准备数据,在插入数据的时候,如果index.type.mapping都没有,es会自动创建 一.数据的准备 curl -XPOST "http://192.168.99 ...

  8. Noip模拟67 2021.10.3

    还是困,不过已经可以用脑子思考问题了 T1 数据恢复 没啥明确的算法,可以说是贪心? 考虑部分分, 链的直接扫, 对于菊花的发现只要根节点在第一个,剩下的点位置不重要 那么按照$a/b$排序,扫一遍就 ...

  9. sort方法和自定义比较器的写法

    摘要 在做一些算法题时常常会需要对数组.自定义对象.集合进行排序. 在java中对数组排序提供了Arrays.sort()方法,对集合排序提供Collections.sort()方法.对自定义对象排序 ...

  10. ASP.NET MVC 中使用 jQuery 实现异步搜索功能

    常见的几种异步请求方式: Ajax.BeginForm   异步提交文本的形式 Ajax.ActionLinkk 文本链接的形式 Client Validataion  客户端的认证 一.用jQuer ...