洛谷 P1801 黑匣子 题解
离线处理;
大体思路就是将数组排序,然后对于第k次询问把不可行的数打上标记,然后从头开始寻找第k个没打标记的点的值
(排序后的数组保证了它是第k小的)。
实现方法:
首先离散化原始数组,得到数组find[],find[i]=j表示原位置为i的数从小到大排序后的位置是j。
a[]数组表示原数组,b[]数组存每次询问到第几个位置。n个数,m个询问。
由于询问的b[]是递增的,所以仅仅需要排序1~b[m]即可;(因为不可能输出b[m]以后的数,所以可以忽略b[m]以后的数对答案的影响)
排序后,倒着处理每次询问,设bo[i]=1表示*排序后*位置是i的这个数不在某次询问的范围内(对于一次询问q,询问的范围就是1~b[q]);
设一个指针now,它所指向的是排序后数组的某一个位置,对于第k次询问now的值就是排序后数组从头开始数第k个没打标记的点的位置。
初始化now指向b[m],然后枚举由于该次询问所额外添加的点j,并把它们打上标记(bo[find[j]]=1)。
PS1:比如说上次询问是1~3区间,这次询问是1~5区间,那么额外添加的点j就是4和5.
PS2:由于4,5指的是原数组a[]中位置,所以应该给find[4],find[5]打标记;
设cnt=0,对于每次枚举,如果find[j]<now,那么就cnt++;
假设当前你求第k小值,如果cnt=0,就表示find[q[k-1]+1~q[k]]都不在now的前边,
因为参与第k-1小比较的值都在now的前面,所以这种情况对于回答第k-1小的值不存在影响
第k-1小的值就是从now往前数第1个没打标记的点u,并将now更新为u
当cnt=1时,这意味着now前面有一个点在求第k-1小的值时是不可以使用的!这代表now这个点从原来的第k小变味了第k-1小。所以now不更新。
但要注意,由于我们是find[j]<now时++cnt,所以可能存在now这个点被标记的情况。在这种情况下now要向后移到第一个没打标记的点。
当cnt>1时,就代表前面的数有很多都不能使用了,这意味着now需要向后移动来保证now所指的位置是第k-1小;
如果bo[now]=1,那么将now向右移动,直到经过了cnt个未标记的点。否则,将now向右移动,直到经过了(cnt-1)个未标记的点;
对于每次询问,ans[i]=排序后now这个位置的值;
时间复杂度是排序的(nlogn)+打标记的O(n)加上改变now的值的O(n)外加一些常数;
#include <bits/stdc++.h>
using namespace std;
int a[];
int b[];
int n,m;
struct haha{
int pos;
int v;
}lala[];
bool cmp(haha x,haha y)
{
return x.v<y.v;
}
int fin[];
int ans[];
int bo[];
int main ()
{
scanf("%d%d",&n,&m);
for(register int i=;i<=n;i++){
scanf("%d",&a[i]);
}
for(register int i=;i<=m;i++){
scanf("%d",&b[i]);
}
for(register int i=;i<=b[m];i++){
lala[i].pos=i;
lala[i].v=a[i];
}
sort(lala+,lala++b[m],cmp);
for(register int i=;i<=b[m];i++){
fin[lala[i].pos]=i;
}
int now=m;
for(register int i=m;i>=;i--){
ans[i]=lala[now].v;
int cnt1=;
for(register int j=b[i-]+;j<=b[i];j++){
if(fin[j]<now) ++cnt1;
bo[fin[j]]=;
}
if(cnt1>){
while(bo[now]) ++now;
int tmp=cnt1-;
int cnt=;
for(register int j=now+;j<=n;j++){
if(bo[j]) continue;
++cnt;
if(cnt==tmp){
now=j;
break;
}
}
}
else if(cnt1==&&bo[now]){
for(register int j=now+;j<=n;j++){
if(bo[j]) continue;
now=j;
break;
}
}
else if(cnt1==){
--now;
while(bo[now]){
--now;
}
}
}
for(register int i=;i<=m;i++){
printf("%d\n",ans[i]);
}
}
洛谷 P1801 黑匣子 题解的更多相关文章
- 洛谷 P1801 黑匣子_NOI导刊2010提高(06)(未完)
P1801 黑匣子_NOI导刊2010提高(06) 题目描述 Black Box是一种原始的数据库.它可以储存一个整数数组,还有一个特别的变量i.最开始的时候Black Box是空的.而i等于0.这个 ...
- 洛谷 P1801 黑匣子_NOI导刊2010提高(06) 题解
昨晚恶补了一下二叉堆的内容 然后就找了几个二叉堆的题来做awa 然后发现用二叉堆做这题复杂度是O(nlogn) 但是有O(n)的解法 (某大佬这么说) 思路大概就是: 利用一个大根堆一个小根堆来维护第 ...
- [洛谷P1801]黑匣子_NOI导刊2010提高(06)
题目大意:两个操作:向一个可重集中加入一个元素:询问第$k$大的数($k$为之前询问的个数加一) 题解:离散化,权值线段树直接查询 卡点:无 C++ Code: #include <cstdio ...
- 洛谷 - P1801 - 黑匣子 - 对顶堆
这道题是提高+省选-的难度,做出来的话对数据结构题目的理解会增加很多. 可以使用一种叫做对顶堆的东西,对顶堆是在线维护第n小的logn的算法.大概的思路是,假如我们要找的是第n小,我们就维护一个大小为 ...
- 洛谷 [P1801] 黑匣子
这道题是一道splay裸题,然而身为蒟蒻的我并不会,所以这道题我维护的是一个大根堆与一个小根堆结合起来的类似沙漏的结构. 本题难点在于询问的不是最大最小值,而是第K小值,所以我们想到了维护这样两个堆, ...
- 洛谷P1801 黑匣子
题目传送门 分析:这题和另外一个题目中位数非常相似,有兴趣可以先看看,比这一题简单.首先暴力模拟还是别想了,估计30%的数据都有点悬.正解应该是用二叉堆.但是如果用一个堆当然不方便,所以建两个堆,一个 ...
- 洛谷 P1801 黑匣子_NOI导刊2010提高(06)
题目描述 Black Box是一种原始的数据库.它可以储存一个整数数组,还有一个特别的变量i.最开始的时候Black Box是空的.而i等于0.这个Black Box要处理一串命令. 命令只有两种: ...
- 洛谷NOIp热身赛题解
洛谷NOIp热身赛题解 A 最大差值 简单树状数组,维护区间和.区间平方和,方差按照给的公式算就行了 #include<bits/stdc++.h> #define il inline # ...
- 洛谷P2827 蚯蚓 题解
洛谷P2827 蚯蚓 题解 题目描述 本题中,我们将用符号 ⌊c⌋ 表示对 c 向下取整. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现 ...
随机推荐
- PHP中变量声明和定义的区别
先记录一下(不知道PHP是不是一样,但是C语言是这样的):把建立空间的声明称之为“定义”,而把不需要建立存储空间的声明称之为“声明”.声明的最终目的是为了提前使用,即在定义之前使用,如果不需要提前使用 ...
- 数据库范式以及ER图
数据库范式包括第一.第二.第三以及BCNF范式,关于范式的探讨,博主在知乎上看见了一篇很不错的文章,分享文中,这边就不再做阐述.地址:https://www.zhihu.com/question/24 ...
- JavaWeb_(SSH论坛)_二、框架整合
基于SSH框架的小型论坛项目 一.项目入门 传送门 二.框架整合 传送门 三.用户模块 传送门 四.页面显示 传送门 五.帖子模块 传送门 六.点赞模块 传送门 七.辅助模块 传送门 导入Jar包 导 ...
- 如何使用EF?
方法1: 新建好项目之后 → 右击类库 → 新建项 → ADO.NET实体数据模型(在Visual C#项中) → 从数据库生成 → 选择你要映射的数据库的数据源(将 『是,在连接字符串中包含敏感数据 ...
- 后盾网lavarel视频项目---5、淘宝镜像cnpm的原理及如何使用
后盾网lavarel视频项目---5.淘宝镜像cnpm的原理及如何使用 一.总结 一句话总结: 原理:把npm上面的所有软件copy过来 使用:npm install -g cnpm --regist ...
- Oracle Rac 测试
#还是使用之前的脚步来进行测试 #Author : Kconnie Pong Oracle@PONGDB:~> more load_balance.sh #!/bin/bash ..} do ...
- 布尔 kotlin(4)
布尔布尔用 Boolean 类型表示,它有两个值: true 和 false .若需要可空引用布尔会被装箱.内置的布尔运算有:|| – 短路逻辑或&& – 短路逻辑 ...
- TODO: Java虚拟机 初始化过程
Java虚拟机 初始化过程: 参考: https://www.cnblogs.com/bhlsheji/p/4017816.html 参考:https://blog.csdn.net/boling_c ...
- kotlin之基本数据类型
数据类型 占用字节数 Double 8 Float 4 Long 4 Int 4 Short 2 Byte 1 数据类型之间的转换 toByte():转换为 ...
- CompletableFuture用法介绍
一.CompletableFuture用法入门介绍 入门介绍的一个例子: package com.cy.java8; import java.util.Random; import java.util ...