255. 第K小数

2024-05-11 00:58
文章标签 小数 255

本文主要是介绍255. 第K小数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接:255. 第K小数

算法分析

据说这道题可以用来练习多种高级数据结构,本题是用可持久化线段树解的。算法分析可参考进阶指南。需要注意的是:

  1. 线段树的空间开销。离散化后,取值区间最大为[1,n]。这是值域。在值域上建立初始线段树,因为不是按照层次编号,所以开销为 2 ∗ n 2*n 2n。后面 n n n个数字分别插进去,建可持久化树,每次开销为 l o g n logn logn,共 n n n次。 n n n最大为100000,所以空间总开销 2 ∗ n + 18 ∗ n = 20 n 2*n+18*n=20n 2n+18n=20n足矣。

  2. 时间开销每次插入和查询都是log级别的,因此为 O ( ( n + m ) l o g n ) O((n+m)logn) O((n+m)logn)

  3. v a l [ ] val[] val[]记录离散化后原来的大小,最后输出时需要还原。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
#define ll long long 
const int N = 1e5 + 10;
int a[N], lsh[N], val[N];
int n, m;
struct node
{int lc, rc, dat; // dat是该点的数字个数  
}tr[2*N+18*N];
int root[N], tot;
int re()
{int x = 0, f = 1; char c = getchar();while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}return x * f; 
}
int szbuild(int l, int r)
{int p = ++tot;if (l == r){tr[p].dat = 0; return p;}int mid = (l + r) >> 1;tr[p].lc = szbuild(l, mid);tr[p].rc = szbuild(mid + 1, r);tr[p].dat = tr[tr[p].lc].dat+ tr[tr[p].rc].dat;return p;
}
int szchange(int cur, int l, int r, int x, int val)
{int p = ++tot;tr[p] = tr[cur];if (l == r){tr[p].dat += val; return p;  // 有可能有重复的  }int mid = (l + r) >> 1;if (x <= mid)tr[p].lc = szchange(tr[cur].lc, l, mid, x, val);else tr[p].rc = szchange(tr[cur].rc, mid + 1, r, x, val);tr[p].dat = tr[tr[p].lc].dat + tr[tr[p].rc].dat;return p;
}
int szask(int pr, int ql, int l, int r, int k)
{if (l == r) return val[l];  // 因为是对值域建树,所以直接范围的l就是值,还原回原先的数  int mid = (l + r) >> 1;int num = tr[tr[pr].lc].dat - tr[tr[ql].lc].dat;  // [l,r]区间有多少数  if (num >= k) return szask(tr[pr].lc, tr[ql].lc, l, mid, k);else return szask(tr[pr].rc, tr[ql].rc, mid + 1, r, k - num);
}
int main()
{n = re(); m = re();for (int i = 1; i <= n; ++i) a[i] = lsh[i] = re();// 离散化  sort(lsh + 1, lsh + n + 1);int cnt = unique(lsh + 1, lsh + n + 1) - lsh - 1;  // 离散化后取值范围是[1, cnt]  for (int i = 1; i <= n; ++i){int t = a[i];a[i] = lower_bound(lsh + 1, lsh + n + 1, a[i]) - lsh;val[a[i]] = t;}	// 初始建树 root[0] = szbuild(1, cnt); // 将1 ~ n个数字构建可持久化线段树,相当于单点修改 for (int i = 1; i <= n; ++i) root[i] = szchange(root[i-1], 1, cnt, a[i], 1);// m个查询 int l, r, k;for (int i = 1; i <= m; ++i){l = re(); r = re(); k = re();printf("%d\n", szask(root[r], root[l-1], 1, cnt, k));} return 0;
}

反思与总结

数据结构题码量大、思维要求低,细节多。得多练。

这篇关于255. 第K小数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/978060

相关文章

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

Java中四舍五入保留两位小数或不保留小数

//四舍五入,不保留小数; float gr = 8; float gc = 3; DecimalFormat df1 = new DecimalFormat("0");//格式化小数,不足的补0 String gaver = df1.format((gr/gc));//返回的是String类型的      //四舍五入,保留两位小数; float g1 = 111; f

C/C++两点坐标求距离以及C++保留两位小数输出,秒了

目录 1. 前言 2. 正文 2.1 问题 2.2 解决办法 2.2.1 思路 2.2.2 代码实现 3. 备注 1. 前言 依旧是带来一个练手的题目,目的就一个,方法千千万,通向终点的方式有很多种,没有谁与谁,我们都是为了成为更好的自己。 2. 正文 2.1 问题 题目描述: 输入两点坐标(X1,Y1),(X2,Y2),计算并输出两点间的距离。 输入格式:

【舍入,取整,取小数,取余数丨Excel 函数】

数学函数 1、Round函数 Roundup函数 Rounddown函数 取整:(Int /Trunc)其他舍入函数: 2、Mod函数用Mod函数提取小数用Mod函数 分奇偶通过身份证号码判断性别 1、Round函数 Roundup函数 Rounddown函数 Round(数字,保留几位小数)(四舍五入) Roundup (向上舍入) 在x轴上向正负无穷大靠近 Roun

题目:输入 5 个数(含负数、小数)将它们按由小到大的顺序排列起来。提示:需要排序的数字通过参数传递进来。

题目:输入 5 个数(含负数、小数)将它们按由小到大的顺序排列起来。 提示:需要排序的数字通过参数传递进来。 例如: 输入:-1 2.1 -3 5 7 输出: -3 -1 2.1 5 7 import java.util.Scanner;public class FuShuXiaoShuPaiXu {public static void swap(double[] arr,int a,in

带小数的String转整数Integer

其实String和Integer、Float、Double等相互转换这都很容易。可是带小数的String转Float、Double可能会出现“模糊数字”。 那么怎么避免呢?见下实例和结论。 System.out.println("**********2.4***********");String a = "2.4"; System.out.println(a); // 2.4System.o

POJ1001高精度小数运算

题目链接:http://poj.org/problem?id=1001 题目意思:输入实数R和次数n,输出pow(R,n)?     0.0 < R < 99.999  0 < n <= 25 分析:数据规模很小,直接n次R的乘法,不会C++大数,暴力都没A过,然后就试java了,java不知道double有没有,于是用BigInteger做,然后移动小数位。第一发RE了,在测试10.000

#1133 : 二分·二分查找之k小数 ( 快速排序, 分治 OR nth_element() 函数)

#1133 : 二分·二分查找之k小数 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回里我们知道Nettle在玩《艦これ》,Nettle的镇守府有很多船位,但船位再多也是有限的。Nettle通过捞船又出了一艘稀有的船,但是已有的N(1≤N≤1,000,000)个船位都已经有船了。所以Nettle不得不把其中一艘船拆掉来让位给新的

关于el-table的show-summary,合计栏不显示以及保留两位小数问题

<el-tableref="table1"v-loading="loading":data="":stripe="true"height="600"show-summary:summary-method="getSummaries":show-overflow-tooltip="true">...</el-table> 合计部分不显示的问题 updated() {this.$nextTi

【MATLAB源码-第255期】基于matlab的长鼻浣熊优化算法(COA)无人机三维路径规划,输出做短路径图和适应度曲线.

操作环境: MATLAB 2022a 1、算法描述 长鼻浣熊优化算法(Coati Optimization Algorithm,COA)是一种新兴的群体智能优化算法,其灵感来源于长鼻浣熊在自然界中的觅食行为。长鼻浣熊是一种生活在美洲热带和亚热带森林中的哺乳动物,它们以群体形式活动,具有高度的社会性和合作性。这种动物以敏锐的嗅觉和灵活的爪子著称,能够有效地找到隐藏在环境中的食物资源。COA 模