首页 > 其他分享 >洛谷题单指南-二叉树-P5076 【深基16.例7】普通二叉树(简化版)

洛谷题单指南-二叉树-P5076 【深基16.例7】普通二叉树(简化版)

时间:2024-03-14 16:44:43浏览次数:28  
标签:迭代 16 int 简化版 复杂度 tree pos 查找 二叉树

原题链接:https://www.luogu.com.cn/problem/P5076

题意解读:此题本质上是要实现一个二叉搜索树的功能。

解题思路:

从数据规模10^4来看,只要复杂度在n^2范围内基本上是可以通过的,下面给出两种做法:

1、有序数组法

对应5个操作的实现逻辑如下:

操作一:查x的排名。直接通过二分查找>=x的第一个数的位置pos,pos即x的排名,复杂度O(logN);

操作二:查排名x的数。直接返回x下标的元素,复杂度O(1);

操作三:x的前驱。通过二分查找>=x的最小的数的位置pos,x的前驱即pos-1位置的数,不存在要输出 −2147483647,复杂度O(logN);

操作四:x的后继。通过二分查找<=x的最大的数的位置pos,x的后继即pos+1位置的数,不存在要输出2147483647,复杂度O(logN);

操作五:插入x。通过二分查找>=x的最小的数的位置pos,如果pos不存在,则将x添加到最后,否则从pos开始把所有数往后移一位,将x放入pos,复杂度<=O(logN + N)。

总体复杂度<O(N^2)

100分代码:

 

#include <bits/stdc++.h>
using namespace std;

const int N = 10005;

int a[N], idx;

int bs1(int x)
{
    int l = 1, r = idx, ans = -1;
    while(l <= r)
    {
        int mid = (l + r) >> 1;
        if(a[mid] >= x) ans = mid, r = mid - 1;
        else l = mid + 1;
    }
    if(ans == -1) ans = idx + 1; //如果不存在,要找的位置就是当前最后一个数的下一个位置
    return ans;
}

int bs2(int x)
{
    int l = 1, r = idx, ans = -1;
    while(l <= r)
    {
        int mid = (l + r) >> 1;
        if(a[mid] <= x) ans = mid, l = mid + 1;
        else r = mid - 1;
    }
    if(ans == -1) ans = 0; //如果不存在,要找的位置就是当前第一个数前一个位置
    return ans;
}

int main()
{
    int q, op, x;
    cin >> q;
    while(q--)
    {
        cin >> op >> x;
        if(op == 1)
        {
            int r = bs1(x); //查找第一个>=x的位置,即x的排名
            cout << r << endl;
        } 
        else if(op == 2) cout << a[x] << endl; //返回排名x的数
        else if(op == 3) 
        {
            int pos = bs1(x); //查找>=x的最小的数的位置pos
            if(pos - 1 > 0) cout << a[pos - 1] << endl; //x的前驱即pos-1位置的数
            else cout << -2147483647 << endl; //不存在要输出 −2147483647
        }
        else if(op == 4) 
        {
           int pos = bs2(x); //查找<=x的最大的数的位置pos
           if(pos + 1 <= idx) cout << a[pos + 1] << endl; //x的后继即pos+1位置的数
           else cout << 2147483647 << endl; //不存在要输出2147483647
        }
        else
        {
            int pos = bs1(x); //查找>=x的最小的数的位置pos
            
            if(pos == idx + 1) a[++idx] = x; //如果没有找到,说明所有数都比x小,添加到最后
            else 
            {
                for(int i = idx; i >= pos; i--) 
                    a[i + 1] = a[i]; //从pos开始把所有数往后移一位
                a[pos] = x; //将x放入pos
                idx++; //最后一个元素的位置更新
            }
        }
    }

    return 0;
}

2、set法(底层是红黑树-一种平衡的二叉搜索树)

set有两个实现了二分查找功能的函数要介绍一下:

s.lower_bound(x); //返回容器中第一个大于等于x的数的迭代器 

s.upper_bound(x);//返回容器中第一个大于x的数的迭代器

对应5个操作的实现逻辑如下:

操作一:查x的排名。通过lower_bound(x)查找第一个>=x的数的迭代器it,从迭代器s.begin()遍历到it,累计cnt即为x的排名,复杂度<=O(logN + N);

操作二:查排名x的数。从迭代器s.begin()遍历x次,取第x个元素的值,复杂度<=O(N);

操作三:x的前驱。通过lower_bound(x)查找第一个>=x的数的迭代器it,x的前驱即it--位置的数,不存在要输出 −2147483647,复杂度O(logN);

操作四:x的后继。通过upper_bound(x)查找第一个>x的数的迭代器it,x的后继*it,不存在要输出2147483647,复杂度O(logN);

操作五:插入x。通过insert(x)插入数据,复杂度O(logN)。

总体复杂度<O(N^2)

100分代码:

#include <bits/stdc++.h>
using namespace std;

set<int> tree;

int main()
{
    int q, op, x;
    cin >> q;
    while(q--)
    {
        cin >> op >> x;
        if(op == 1)
        {
            int cnt = 1;
            set<int>::iterator end = tree.lower_bound(x);  //查找第一个>=x的数的迭代器
            for(set<int>::iterator it = tree.begin(); it != end; it++) cnt++; //从迭代器s.begin()遍历到it,累计cnt即为x的排名
            cout << cnt << endl;
        } 
        else if(op == 2) 
        {
            int cnt = 1;
            set<int>::iterator it = tree.begin();
            while(it != tree.end() && cnt != x) it++, cnt++; //从迭代器s.begin()遍历x次,取第x个元素的值
            cout << *it << endl;
        }
        else if(op == 3) 
        {
            set<int>::iterator it = tree.lower_bound(x);  //查找第一个>=x的数的迭代器it
            if(it != tree.begin()) cout << *(--it) << endl; //x的前驱即--it位置的数
            else cout << -2147483647 << endl; //不存在要输出 −2147483647
        }
        else if(op == 4) 
        {
            set<int>::iterator it = tree.upper_bound(x); //查找第一个>x的数的迭代器it
            if(it != tree.end()) cout << *it << endl; //x的后继*it
            else cout << 2147483647 << endl; //不存在要输出2147483647
        }
        else tree.insert(x); //插入数据
    }

    return 0;
}

 

标签:迭代,16,int,简化版,复杂度,tree,pos,查找,二叉树
From: https://www.cnblogs.com/jcwy/p/18073210

相关文章

  • [USACO | Python] 201602B2 Circular Barn
    作为当代建筑的粉丝,农民约翰(John)建造了一个完美圆形的新谷仓。在里面,谷仓由n环组成房间,从1…n的顺时针方向编号。房间的有n个(1<=n<=1000)。每一间房间都有三扇门,两扇分别通往临近的房间,一扇通往谷仓的外面。FarmerJohn想要有准确的ri头牛在房间r中(1<=ri<=100),他......
  • 617. 合并二叉树c
    /***Definitionforabinarytreenode.*structTreeNode{*intval;*structTreeNode*left;*structTreeNode*right;*};*/structTreeNode*mergeTrees(structTreeNode*root1,structTreeNode*root2){if(!root1&&!roo......
  • 滴水逆向笔记系列-c语言总结4-15.switch语句反汇编-16.指针1-17.指针2
    第十五课c语言8switch语句初步测试感觉switch在反汇编的语句和if语句的唯一差别就是jcc语句比较集中当分支大于四条时,switch的反汇编开始变3为switch传入的值,1是case最小值,4是case最大值减1,算出偏移量后通过偏移量4加上基址就可以在大表中获取要输出的case语句的地址当现在case......
  • 257. 二叉树的所有路径c
    /***Definitionforabinarytreenode.*structTreeNode{*intval;*structTreeNode*left;*structTreeNode*right;*};*//***Note:Thereturnedarraymustbemalloced,assumecallercallsfree().*/chartemp[200]={0};v......
  • 【5V 转 3.3V,3V,2.5V芯片首选】PW2162高效恒压转换器,外围电路超简单
    在现代电子设备高速发展的今天,一款高效、稳定的电源管理芯片对于设备的性能至关重要。PW2162,作为一款完全集成、高效的2A同步整流降压转换器,凭借其出色的性能和广泛的应用领域,正引领着电源管理领域的新纪元。首先,让我们深入了解一下PW2162的独特之处。这款转换器在宽输出电流负载......
  • LCR 016. 无重复字符的最长子串(中)
    目录题目题解:滑动窗口题目给定一个字符串s,请你找出其中不含有重复字符的最长连续子字符串的长度。示例1:输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子字符串是"abc",所以其长度为3示例2:输入:s="bbbbb"输出:1解释:因为无重复字符的最长子字......
  • 蛋糕甜品奶茶订购系统 微信小程序 c7164
    在蛋糕订购小程序的前期,即需求分析阶段,我们对用户的需求进行了详细的描述,并且在需求规范中有详细的描述和阐明。根据系统需求的分析,对蛋糕订购的管理进行了整体的设计。着重对软件模块的设计进行了详细的分析,以达到对系统的需求。重点阐述了系统的划分、接口的确定、各模块间的......
  • 洛谷题单指南-二叉树-P4913 【深基16.例3】二叉树深度
    原题链接:https://www.luogu.com.cn/problem/P4913题意解读:计算二叉树的深度解题思路:首先介绍二叉树的存储方式,对于本题,直接用数组模拟,数组的下标即节点号structnode{intl,r;}tree[N];tree[i].l存的是节点i的左子结点,tree[i].r存的是节点i的右子节点。计算深度至......
  • 16_策略模式
    策略模式是一种行为型设计模式,它定义了一系列的算法,并将每个算法封装到独立的类中,使它们可以互相替换。策略模式使得算法可以独立于客户端而变化,客户端可以根据需要选择不同的算法。策略模式有三个主要角色:环境类(Context):它持有一个策略对象的引用,并在需要的时候调用策略对象的......
  • RedisCluster集群中的插槽为什么是16384个?
    RedisCluster集群中的插槽为什么是16384个?CRC16的算法原理。1.根据CRC16的标准选择初值CRCIn的值2.将数据的第一个字节与CRCIn高8位异或3.判断最高位,若该位为0左移一位,若为1左移一位再与多项式Hex码异或4.重复3至9位全部移位计算结束5.重复将所有输入数据操作完成以上步骤......