首页 > 其他分享 >Acwing255.第k小数

Acwing255.第k小数

时间:2024-03-13 16:46:38浏览次数:274  
标签:cnt include Acwing255 int tr mid now 小数

可持久化权值线段树

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <vector>
#define For(i, j, n) for(int i = j ; i <= n ; ++i)
using namespace std;

const int N = 1e5 + 1, M = 1e4 + 1;

struct node{
    int l, r;
    int cnt;
}tr[N * 4 + 17 * N];

int n, m, idx, a[N], root[N];
vector<int> num;

int build(int l, int r)
{
    int p = ++idx;
    tr[p].cnt = 0;
    if(l == r)
        return p;
    int mid = l + r >> 1;
    tr[p].l = build(l, mid);
    tr[p].r = build(mid + 1, r);
    return p;
}

int insert(int last, int l, int r, int tar)
{
    int now = ++idx;
    tr[now] = tr[last];
    if(l == r)
    {
        tr[now].cnt++;
        return now;
    }
    int mid = l + r >> 1;
    if(tar <= mid)
        tr[now].l = insert(tr[last].l, l, mid, tar);
    if(tar > mid)
        tr[now].r = insert(tr[last].r, mid + 1, r, tar);
    tr[now].cnt = tr[tr[now].l].cnt + tr[tr[now].r].cnt;
    return now;
}

int query(int L, int R, int l, int r, int k)
{
    if(l == r) 
        return l;
    int mid = l + r >> 1;
    int c = tr[tr[R].l].cnt - tr[tr[L].l].cnt;
    if(c < k)
        return query(tr[L].r, tr[R].r, mid + 1, r, k - c);
    else
        return query(tr[L].l, tr[R].l, l, mid, k);
}

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        num.push_back(a[i]);
    }
    sort(num.begin(), num.end());
    num.erase(unique(num.begin(), num.end()), num.end());
    root[0] = build(0, num.size() - 1);
    for(int i = 1; i <= n; i++)
        root[i] = insert(root[i - 1], 0, num.size() - 1, lower_bound(num.begin(), num.end(), a[i]) - num.begin());
    int l, r, k;
    while(m--)
    {
        scanf("%d%d%d", &l, &r, &k);
        printf("%d\n", num[query(root[l - 1], root[r], 0, num.size() - 1, k)]);
    }
    return 0;
}

一开始粗心大意,写错了几个细节,卡了一会:

1.tr的声明:一开始按照习惯写成了tr[N << 2 + 17 * N],这样子会因为优先级的问题,开出过大的数组;

2.build的时候,记得要先把cnt置为0,正确初始化;

3.insert完以后记得pushup(即用儿子的信息更新当前节点信息)

另外,如果这道题问的是“[l,r]区间内有多少个数小于等于ki”,那么就可以用这个链接里的可持久化方法来做:

(离线/树状数组)区间小于等于k的个数 - 知乎 (zhihu.com)

只要是满足区间可加性的问题,都可以用上面的方法来维护,但是这道问题问的区间内第k小数并不满足这个性质。

标签:cnt,include,Acwing255,int,tr,mid,now,小数
From: https://www.cnblogs.com/smartljy/p/18070966

相关文章

  • abc234E 不小于X的数位构成等差数列的最小数字
    给定X,求不小于X的整数,满足各个数位正好构成等差数列。1<=X<=1E17直接枚举首项和公差,找出所有可行的解,取最优值即可。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#definerep(i,a,b)for(inti=a;i<=b;i++)#defineper(i,a,b)for(inti=b;i>=a;......
  • 分化小数
     输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b<=1000000,c<=100.输入包含多组数据,结束标记为a=b=c=0. #include<iostream>#include<iomanip>#include<sstream>intmain(){inta,b,c;std::stringresult;std::stringstreamss;......
  • 计算机进行小数运算时出错的原因
    首先,计算机进行小数运算时出错的原因可以归结为以下几个方面:精度限制:计算机内部使用二进制表示数据,而二进制无法精确表示所有的小数。这会导致在进行小数运算时,可能会产生舍入误差。例如,0.1在二进制中是一个无限循环小数,计算机只能近似表示,从而导致运算结果的不精确。舍入......
  • 166. 分数到小数(中)
    目录题目题解正解题目给定两个整数,分别表示分数的分子numerator和分母denominator,以字符串形式返回小数。如果小数部分为循环小数,则将循环的部分括在括号内。如果存在多个答案,只需返回任意一个。对于所有给定的输入,保证答案字符串的长度小于104。示例1:输入:nu......
  • 《程序是怎样跑起来的》第三章“计算机进行小数运算时出错的原因”
    当我们使用计算机进行小数运算时,可能会遇到一些意想不到的错误。这些错误并非计算机的缺陷,而是由于其内在的特性所导致的。深入了解这些原因,有助于我们更好地理解计算机运算的局限性和应对策略,从而在编程和数据处理时更加得心应手。计算机在进行小数运算时出错的原因包括二进......
  • 第三章 计算机进行小数运算
    用二进制数来表示整数和整数的方法有很大不同,例如:0次幂前面的位的位权按照1次幂、2次幂……的方式递增,0次幂以后的位的位权按照-1次幂、-2次幂……的方式递减(这一规律在十进制数和16进制数中也同样适用)。在了解了将二进制数表示的小数转化成10进制数的方法后,计算机运算出错的原因......
  • 计算机进行小数运算时出错的原因
    通过此章的学习我了解的计算机出错的几个重大原因,以及什么是浮点数,让我对计算机有了更加深刻的认知和理解,我也了解到如何在实际程序中确认和如何避免计算机出错计算机运算出错的原因计算机之所以会出现运算错误,是因为“有一些十进制数的小数无法转换成二进制数”。代码清单3-1......
  • vue3 ts用正则表达式校验两位小数和校验整数的方法
    <el-col:span="12"><el-form-itemlabel="贷款金额"prop="loanAmount"><el-input-numberv-model="props.loanAmount":min="0"@change="checkIntegerNumber('loanAmount')"controls......
  • 程序是怎样跑起来第三章小数运算出错原因
    大家可能会认为“万能的计算机是不会出现计算错误的”。但实际上,依然存在程序运行后无法得到正确数值的情况。其中,小数运算就是一个典型的例子。在本章中我们首先了解了将二进制表示的小数转换成十进制的方法,这样便于理解计算机运算出错的原因,计算机之所以会出现运算错误,是因为“......
  • 第三章 计算机在计算小数时会出错的原因
    我们习惯性认为计算机在计算是不会出错,可事实并非如此。本章节第1节举出了一个例子“将0.1累加100次的结果不是10”。C语言程序结果得出10.000002。但出现这种去看并不是计算机故障或者程序编写错误的原因。想了解为什么出现错误,就要做到计算机是如何处理小数的。第2节告诉我们如......