首页 > 其他分享 >pbds的应用

pbds的应用

时间:2023-07-18 21:34:30浏览次数:43  
标签:pbds 下标 int rbt tree pos rope 应用

pbds大法好

头文件及命名空间

#include<bits/extc++.h>
using namespace __gnu_pbds;

调用

tree<pair<int,int>,null_type,less<pair<int,int> >,rb_tree_tag,tree_order_statistics_node_update>rbt;
tree<pair<int,int>,null_type,less<pair<int,int> >,splay_tree_tag,tree_order_statistics_node_update>rbt;

具体用法

T.insert(x) //插入一个数 x

T.erase(x) //删除一个数 x,如果没有这个数,那么什么都不会做

T.order_of_key(x) //查询一个数 x 的排名,返回比这个数小的数的个数,即使原树中没有这个数也可以查询

*T.find_by_order(x-1) //查询排名为 x 的数,

由于返回的是迭代器(和指针差不多的用途),所以要用 * 来获取地址所存的值,

并且 tree 里面的排名是从零开始的,所以要查排名为 x-1 的数的值

*T.lower_bound(x)查找第一个大于等于 x 的数,返回的也是迭代器,并且即使原树中没有 x 也可以查找

当然前提是这个tree的类型是less<int>

如果类型是greater<int>,查找的就是第一个小于等于 x 的数

*T.upper_bound(x)查找第一个大于/小于 x 的数,同上

T.join(b) b并入T 前提是两棵树的key的取值范围不相交,即两棵树里面没有相同的数

T.split(v,b) 小于等于v的元素属于T,其余的属于b

需要注意的是tree会自动去重,

所以如果要使它里面存多个相同的数,就需要一点投机取巧的方法

P6136 【模板】普通平衡树(数据加强版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
#include<bits/extc++.h>
using namespace __gnu_pbds;
using namespace std;
tree<pair<int,int>,null_type,less<pair<int,int> >,rb_tree_tag,tree_order_statistics_node_update>rbt;
int n,m,cnt,ans,last;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int x;
        cin>>x;
        rbt.insert(make_pair(x,++cnt));
    }
    for(int i=1;i<=m;i++)
    {
        int op,x;
        cin>>op>>x;
        x^=last;
        if(op==1)
        {
            rbt.insert(make_pair(x,cnt++));
        }
        if(op==2)
        {
            auto it=rbt.lower_bound(make_pair(x,0));
            rbt.erase(it);
        }
        if(op==3)
        {
            last=rbt.order_of_key(make_pair(x,0))+1;
        }
        if(op==4)
        {
            last=rbt.find_by_order(x-1)->first;
        }
        if(op==5)
        {
            last=rbt.find_by_order(rbt.order_of_key(make_pair(x,0))-1)->first;
        }
        if(op==6)
        {
            last=rbt.find_by_order(rbt.order_of_key(make_pair(x,2147483647)))->first;
        }
        if(op>2)
            ans^=last;
    }
    cout<<ans;
    return 0;
}

P3369 【模板】普通平衡树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
#include<bits/extc++.h>
using namespace __gnu_pbds;
using namespace std;
const int N=100005;
int ans,flag;
cc_hash_table<int,int>f;
tree<pair<int,int>,null_type,less<pair<int,int> >,rb_tree_tag,tree_order_statistics_node_update>rbt;
int main()
{
    //freopen("pbds.in","r",stdin);
    //freopen("pbds.out","w",stdout);
    ios::sync_with_stdio(0);
    int n,op,x;
    cin>>n;
    while(n--)
    {
        cin>>op>>x;
        if(op==1) rbt.insert(make_pair(x,++f[x]));
        if(op==2) rbt.erase(make_pair(x,f[x]--));
        if(op==3) cout<<(rbt.order_of_key(make_pair(x,1))+1)<<endl;
        if(op==4) cout<<(rbt.find_by_order(x-1)->first)<<endl;
        if(op==5) cout<<(rbt.find_by_order(rbt.order_of_key(make_pair(x,0))-1))->first<<endl;
        if(op==6) cout<<(rbt.upper_bound(make_pair(x,10000000000)))->first<<endl;
    }
    return 0;
}

这就完了吗

不不不

pbds封装了一个非常好用的东西

rope(rope大法好,可持久化数据没烦恼)

P3391 【模板】文艺平衡树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

头文件及命名空间

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

调用

rope<类型>变量名

操作

R.push_back(a) //往后插入
R.insert(pos,a)//在pos位置插入a,pos是一个迭代器。
R.erase(pos,n)//在pos位置删除n个元素。
R.replace(pos,x)//从pos开始替换成x
R.substr(pos,x)//从pos开始提取x个变量。

 区间反转

其实非常简单,只要使用两个rope,一个正着建立,一个反向建立,然后通过具体的插入操作实现就可以了

具体操作

  如果你把rope定义为string:

    insert(int pos, string &s, int n) 将字符串s的前n位插入rope的下标pos处,如没有参数n则将字符串s的所有位都插入rope的下标pos处 (补充地址知识:如果你不想从字符串下标为0(即第一个字符)的地址开始取          n位,就将你想开始取的地址代入。如s+1表示从字符串下标为1(即第二个字符)的地址开始取n位。int、char等变量类型的数组都适用这种方法来更改数组操作的起始位置。)

    append(string &s,int pos,int n) 把字符串s中从下标pos开始的n个字符连接到rope的结尾,如没有参数n则把字符串s中下标pos后的所有字符连接到rope的结尾,如没有参数pos则把整个字符串s连接到rope的结尾(这里已经给你起始位置参数pos了就没必要用上述的取地址方法了哈)

    (insert和append的区别:insert能把字符串插入到rope中间,但append只能把字符串接到结尾)

 

    substr(int pos, int len) 提取rope的从下标pos开始的len个字符

 

      at(int x) 访问rope的下标为x的元素

    

    erase(int pos, int num) 从rope的下标pos开始删除num个字符

 

    copy(int pos, int len, string &s) 从rope的下标pos开始的len个字符用字符串s代替,如果pos后的位数不够就补足

 

      replace(int pos, string &x);//从rope的下标pos开始替换成字符串x,x的长度为从pos开始替换的位数,如果pos后的位数不够就补足

 

    以上是常用操作,不常用操作这里就不再赘述。

 

    如果你把rope定义为int(这里只是以int为例):

     insert(int pos, int *s, int n) 将int数组(以下的s都是int数组)s的前n位插入rope的下标pos处,如没有参数n则将数组s的所有位都插入rope的下标pos处

 

    append(int *s,int pos,int n) 把数组s中从下标pos开始的n个数连接到rope的结尾,如没有参数n则把数组s中下标pos后的所有数连接到rope的结尾,如没有参数pos则把整个数组s连接到rope的结尾

 

      substr(int pos, int len) 提取rope的从下标pos开始的len个数

 

    at(int x) 访问rope的下标为x的元素

    

    erase(int pos, int num) 从rope的下标pos开始删除num个数

 

    copy(int pos, int len, int *s) 从rope的下标pos开始的len个数用数组s代替,如果pos后的位数不够就补足

 

      replace(int pos, int *x);//从rope的下标pos开始替换成数组x,x的长度为从pos开始替换的位数,如果pos后的位数不够就补足

文艺平衡树代码

#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
int n,m;
int l,r;
rope<int> rpp,rpn;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    rpp.push_back(0),rpn.push_back(0);
    for(int i=1;i<=n;++i)
        rpp.push_back(i),rpn.push_back(n-i+1);
    while(m--)
    {
        cin>>l>>r;
        rpp.insert(r+1,rpn.substr(n-r+1,r-l+1)),
        rpn.insert(n-l+2,rpp.substr(l,r-l+1));
        rpp.erase(l,r-l+1),rpn.erase(n-r+1,r-l+1);
    }
    for(int i=1;i<=n;++i) printf("%d ",rpp[i]);
    return 0;
}

附二逼平衡树代码

P3380 【模板】二逼平衡树(树套树) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;
const int INF=100000000,N=3e6+5;;
int n,m,a[N],tot,rt,lch[N],rch[N];
tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>tr[N];
void insert(int& p,int l,int r,int k,int pos,bool op)
{
    if(!p)p=++tot;
    if(op)tr[p].insert(pos);
    else tr[p].erase(pos);
    if(l==r)return ;
    int mid=(l+r)>>1;
    if(k<=mid)insert(lch[p],l,mid,k,pos,op);
    else insert(rch[p],mid+1,r,k,pos,op);
}
int getrank(int& p,int l,int r,int k,int ql,int qr)
{
    if(!p)p=++tot;
    if(r<=k)return tr[p].order_of_key(qr+1)-tr[p].order_of_key(ql);
    int mid=(l+r)>>1,ans=getrank(lch[p],l,mid,k,ql,qr);
    if(k>mid)ans+=getrank(rch[p],mid+1,r,k,ql,qr);
    return ans;
}
int kth(int& p,int l,int r,int k,int ql,int qr)
{
    if(!p)p=++tot;
    if(l==r)return l;
    int mid=(l+r)>>1;
    int cnt=tr[lch[p]].order_of_key(qr+1)-tr[lch[p]].order_of_key(ql);
    if(cnt>=k)return kth(lch[p],l,mid,k,ql,qr);
    else return kth(rch[p],mid+1,r,k-cnt,ql,qr);
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)    scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)insert(rt,0,INF,a[i],i,1);
    for(int i=1;i<=m;i++)
    {
        int op,l,r,pos,k;
        scanf("%d",&op);
        if(op!=3)
            scanf("%d%d",&l,&r);
        else scanf("%d",&pos);
        scanf("%d",&k);
        if(op==1)    printf("%d\n",getrank(rt,0,INF,k-1,l,r)+1);
        else if(op==2)    printf("%d\n",kth(rt,0,INF,k,l,r));
        else if(op==3)
        {
            insert(rt,0,INF,a[pos],pos,0);
            insert(rt,0,INF,a[pos]=k,pos,1);
        }
        else if(op==4)
        {
            int rk=getrank(rt,0,INF,k-1,l,r)+1;
            if(rk==1) printf("-2147483647\n");
            else printf("%d\n",kth(rt,0,INF,rk-1,l,r));
        }
        else
        {
            int rk=getrank(rt,0,INF,k,l,r)+1;
            if(rk>r-l+1) printf("2147483647\n");
            else printf("%d\n",kth(rt,0,INF,rk,l,r));
        }
    }
    return 0;
}

平衡树套平衡树

P8306 【模板】字典树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

AC不了,常数巨大

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/trie_policy.hpp>
using namespace std;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9'){ if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
char buffer[3000005];
signed main(){
    int T = read();
    while(T--){
        __gnu_pbds::trie<string, __gnu_pbds::null_type, __gnu_pbds::trie_string_access_traits<>,
                    __gnu_pbds::pat_trie_tag, __gnu_pbds::trie_prefix_search_node_update> trie;
        int n = read(), q = read();
        for(int i = 1; i <= n; i++){
            scanf("%s", buffer);
            trie.insert(string(buffer));
        }
        while(q--){
            int ans = 0;
            scanf("%s", buffer);
            auto range = trie.prefix_range(string(buffer));
            for(auto it = range.first; it != range.second; it++) ans++;
            printf("%d\n", ans);
        }
    }
    return 0;
}

 

标签:pbds,下标,int,rbt,tree,pos,rope,应用
From: https://www.cnblogs.com/mingloch/p/17564175.html

相关文章

  • socket应用的例子
    当使用C语言实现Socket编程时,可以通过系统提供的网络库来实现网络通信。以下是一个简单的示例,演示了如何创建一个简单的服务器和客户端,实现客户端向服务器发送消息并接收回复的功能。服务器端(server.c)#include<stdio.h>#include<stdlib.h>#include<string.h>#include......
  • redis常见的数据类型以及应用场景
    Redis支持多种数据类型,每种数据类型都有其独特的特点和应用场景。以下是Redis常见的数据类型以及它们的应用场景:字符串(String):存储单个值或对象的序列化数据。应用场景:缓存、计数器、分布式锁等。哈希表(Hash):存储多个字段和值的散列数据结构,可以看作是一个关联数组。应用场......
  • 计讯物联5G千兆网关TG463在电力智能巡检机器人的应用功能解析
    项目背景随着国家智能电网建设加速推进,投资规模持续扩大,我国电网智能化、信息化不断提高,传统的电力运维与管理模式早已不能满足智能电网快速发展的需求。因此,在5G无线通信、人工智能、物联网、云计算、大数据、电力等前沿技术的高度融合下,以替代人工巡检为目的的电力智能巡检机器......
  • iThinkAir代码解释器对照Code Interpreter的应用案例
    前几天OpenAI对Plus会员开放了CodeInterpreter功能,有人说是王炸,有人说是核弹级更新,也有人说是继ChatGPT之后再度让人感受到震撼和颠覆的产品。时隔几天,iThinkAir也创造了自己的"代码解释器"。下面列举iThinkAir"代码解释器"的十几个应用案例,大家可以和CodeInterpreter对照一......
  • 计讯物联智慧景区应用解决方案,开启交互式智慧旅游新篇章
    方案背景后疫情时代,旅游市场逐步回暖。随着游客的旅游需求趋向个性化、多元化,景区的数字化转型升级势在必行。在此背景下,计讯物联充分发挥5G、云计算、物联网、大数据等技术的应用价值,以技术创新推动业务创新,面向全国大小景区全新打造智慧景区应用解决方案,以此提高景区整体运营管......
  • 水位控制器的应用优势
    水是一种宝贵的资源,对生命至关重要。然而,它也是一种有限的资源,其可用性越来越有限。管理用水对于确保每个人和所有需要的人都有足够的水是至关重要的。这就是水位控制器的作用所在。在这篇文章中,我们将探讨为什么我们需要水位控制器,以及它如何使我们受益。首先,水位控制器帮助我们节......
  • 数字孪生技术在医疗领域的应用:精准诊断与个性化治疗
    随着科技的不断进步,数字孪生技术正逐渐融入医疗领域,为医学研究、诊断和治疗带来了新的可能性。数字孪生是指将现实世界的实体或过程通过数字化方式呈现出来,以实现仿真、模拟和预测。在医疗领域,数字孪生技术能够模拟人体器官、疾病进程和药物反应等关键信息,为医生和研究人员提供更......
  • python在人工智能领域的应用
    Python在人工智能领域的应用人工智能(ArtificialIntelligence,AI)是近年来快速发展的一个领域,它涉及到机器学习、深度学习、自然语言处理等技术。而Python作为一种高级编程语言,在人工智能领域有着广泛的应用。本文将以代码示例的方式介绍Python在人工智能领域的应用。1.机器学习......
  • 使用podman-compose快速部署应用
    我们对于docker-compose并不陌生,它是一个用于编排多个可能相互依赖的容器的工具。而PodmanCompose项目的目标是作为docker-ompose的替代品,而不需要对docker-compose.yaml文件进行任何修改。要想使用podman-compose需要先安装podman,然后安装podman-compose。Rocky8下安装po......
  • OpenStack原理及在华为云中的应用
    1、云与操作系统虚拟化与云计算的区别虚拟化是将物理资源分配给多个虚拟机,提高硬件资源利用率,重点在于分配物理资源的能力云计算通过管理众多云虚拟机对外提供服务,重点在于提供服务。并且能够多租户之间隔离,按需使用、按量计费操作系统功能云也被当成操作系统,因为它也提供了:......