P3834 【模板】可持久化线段树 1(主席树)难度⭐⭐⭐⭐

P3834 【模板】可持久化线段树 1(主席树)

题解 P3834 【【模板】可持久化线段树 1(主席树)】

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<math.h>

#define ls (p<<1)
#define rs (p<<1|1)
#define mid (l+r)/2
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)

using namespace std;
typedef long long ll;//全用ll可能会MLE或者直接WA,试着改成int看会不会A
const ll N=500007;
const ll INF=1e9+9;
const ll mod=2147483647;
const double EPS=1e-10;//-10次方约等于趋近为0
const double Pi=3.1415926535897;

template<typename T>void read(T &x)
{
    x=0;char ch=getchar();ll f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}x*=f;
}

int n,m,q,cnt;
int a[N],b[N],T[N];
int sum[N<<5],L[N<<5],R[N<<5];

inline void build(int &t,int l,int r)//直接用引用变量&t
{
    int rt=++cnt;//rt是当前节点的编号
    sum[rt]=0;//初始化
    if(l==r)return;
    build(L[rt],l,mid);
    build(R[rt],mid+1,r);
}

inline int update(int p,int l,int r,int x)//p为旧树该位置节点的编号
{
    int rt=++cnt;//新建节点的编号
    L[rt]=L[p];
    R[rt]=R[p];//该节点左右儿子初始化为旧树该位置节点的左右儿子
    sum[rt]=sum[p]+1;//因为插入的a[i](或b[x])在该节点所代表的区间中 所以sum++
    if(l!=r)
    {
        if(x<=mid)L[rt]=update(L[p],l,mid,x);
        //x出现在左子树 因此右子树保持与旧树相同 修改左子树
        else R[rt]=update(R[p],mid+1,r,x);
    }
    return rt;
}

inline int query(int u,int v,int l,int r,int k)
{
    if(l==r)return b[l];
    int num=sum[L[v]]-sum[L[u]];
    if(num>=k)return query(L[u],L[v],l,mid,k);
    else return query(R[u],R[v],mid+1,r,k-num);
}
int sizes;
int main()
{
    read(n),read(m);
    over(i,1,n)
    read(a[i]),b[i]=a[i];
    sort(b+1,b+1+n);
    sizes=unique(b+1,b+1+n)-b-1;
    //size为线段树维护的数组的大小==b数组中不重复的数字的个数
    build(T[0],1,sizes); //初始化 建立一颗空树 并把该树的根节点的编号赋值给T[0]
    over(i,1,n)
    {
        int t=lower_bound(b+1,b+1+sizes,a[i])-b;
        T[i]=update(T[i-1],1,sizes,t);
    }
    //cout<<"123"<<endl;
    while(m--)
    {
        int l,r,k;
        read(l),read(r),read(k);
        printf("%d\n",query(T[l-1],T[r],1,sizes,k));
    }
    return 0;
}

全部评论

相关推荐

02-12 20:22
重庆大学 Java
字节暑期刚入职四天,因为是年前,所以很多正职都放假走了,也就没有给我分配mt,然后有一个老哥在我来的时候给我发了一个landing手册,然后还有关于部门业务的白皮书,还有一些业务代码。然后本人是java面的,进来第一次接触go语言&nbsp;前面几天熟悉了一下go的语法和go的框架,可以读但是还不太会写,然后业务白皮书也看的很头疼,包括landing手册里要了解的很多东西说实话我看文档真的快看死了,一个嵌套一个,问题是我还完全不知道咋用这个我了解的东西,还有就是那个项目代码,那个老哥喊我去写写单测,熟悉一下go的语法,但也进行的很困难(这是我第一段实习,之前都是springboot那一套,真不太熟悉这个)想问问大家的建议,就是我从现在开始到在开年回来之前应该做些什么,我目前就一个想法&nbsp;就是复现一个landing手册上的go框架小项目&nbsp;就是相当于帮自己锻炼锻炼怎么写go&nbsp;或者各位大佬有没有更好的锻炼go语法的建议还有就是大家都在说vibe&nbsp;coding,那我应该怎么锻炼自己使用ai的能力,感觉我除了给一些需求然后它给我生成代码,好像就没别的用法了,那些什么工作流、拆解、skill啥的都不知道从哪一个地方开始,包括我现在正在实习,不知道精力该怎么分配,去网上想找找关于agent开发的一些学习流程,说实话,众说纷纭,有的是从python开始打基础然后系统学那些rag&nbsp;prompt&nbsp;langchain&nbsp;mcp等等,有的是说直接找一个github上的ai项目然后反复问ai,我确实有点迷茫,恳求各位大佬能留下你们宝贵的建议,我一定认真反复深刻学习有一说一&nbsp;我觉得字节饭挺好吃的!
Jasonnnnnn...:直接把项目代码喂给AI然后让它帮你分析,如果组里已经有一些流程图总结的话最好,没有的话自己画一个 Go的话其实只要把基础语法搞明白就行了,项目里很多都是直接让ai帮你写好然后自己稍微改下,不用学的特别深 ai的话,可以自己写一些md文件来搞点小东西,但除非你打算转算法,否则不用把rag langchain学的特别深,了解下就行了
字节跳动公司福利 1371人发布
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务