主席树

可持久化线段树(主席树) 摘要 主席树,又称可持久化线段树,属于可持久化数据结构。“主席”这一名词是由于发明者缩写为HJT,和某位主席拼音缩写相同(有些牵强),故将该数据结构称为主席树。 主席树既保留了线段树的灵活,也拥有了可持久化数据结构的特点,在处理某些特定问题时有着其它数据结构不具有的优势。 本文将首先介绍什么是“可持久化数据结构”,随后介绍主席树的思想,关于代码实现将结合例题讲解。 可持久化数据结构 可持久数据结构... 阅读详情

 主席树


好神的数据结构,不过挺好写的。。

POJ 2104 K-th number

题目大意:
     对一静态序列,每次询问[l,r]中第k大d

主席树模板题

贴代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#define M 100010
using namespace std;


struct Node{
    int l,r,s;
}a[M*50];

int id[M],d[M],cnt,key;
void update(int l,int r,int &pos)
{
    a[++cnt]=a[pos];
    pos=cnt;
    ++a[pos].s;
    if(l==r)
    return ;
    int m=(l+r)/2;
    if(key<=m)
    update(l,m,a[pos].l);
    else
    update(m+1,r,a[pos].r);
}

int query(int l,int r,int x,int y,int k)
{
    if(l==r)
    return l;
    int mid=(l+r)/2,s=a[a[y].l].s-a[a[x].l].s;
    if(k<=s)
    return query(l,mid,a[x].l,a[y].l,k);
    else
    return query(mid+1,r,a[x].r,a[y].r,k-s);
}
bool cmp(int x,int y)
{
    return d[x]<d[y];

}
int n,m;
int b[M];
int root[M];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    scanf("%d",&d[i]),id[i]=i;
    sort(id+1,id+n+1,cmp);
    for(int i=1;i<=n;i++)
    b[id[i]]=i;
    for(int i=1;i<=n;i++)
    {
        root[i]=root[i-1];
        key=b[i];
        update(1,n,root[i]);
    }
    int x,y;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&key);
        int td=query(1,n,root[x-1],root[y],key);
        printf("%d\n",d[id[td]]);

    }
    return 0;
}


HDU 4417 Super Mario

题目大意:

对于一静态序列,询问[l,r]中小于x的个数

这题有树状数组解法,不过我用二分+主席树过了,
(跑得也很快,BIT 200+ms   二分+主席树 500+ms

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define M  100010

using namespace std;

int d[M],b[M],id[M],root[M],cnt,key,T,n,m;
struct Node{

    int l,r,s;
}a[M*30];


bool cmp (int x,int y)
{
    return d[x]<d[y];
}
void update(int &t,int l,int r)
{
    a[++cnt]=a[t];
    t=cnt;
    ++a[t].s;
    if(l==r)
        return ;
    int mid=(l+r)/2;
    if(key<=mid)
        update(a[t].l,l,mid);
    else
        update(a[t].r,mid+1,r);
}
int query(int l,int r,int x,int y,int k)
{
    if(l==r)
        return l;
    int mid=(l+r)/2,s=a[a[y].l].s-a[a[x].l].s;
    if(k<=s)
    return query(l,mid,a[x].l,a[y].l,k);
    else
    return query(mid+1,r,a[x].r,a[y].r,k-s);
}


int main()
{
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++)
    {
        scanf("%d%d",&n,&m);
        printf("Case %d:\n",cas);
        for(int i=1;i<=n;i++)
            scanf("%d",&d[i]),id[i]=i;
        sort(id+1,id+n+1,cmp);
        for(int i=1;i<=n;i++)
            b[id[i]]=i;
        for(int i=1;i<=n;i++)
        {
            root[i]=root[i-1];
            key=b[i];
            update(root[i],1,n);
        }
        for(int i=1,x,y;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&key);
            x++,y++;
            if(d[id[query(1,n,root[x-1],root[y],y-x+1)]]<=key)
            {
                printf("%d\n",y-x+1);

            }
            else
                if(d[id[query(1,n,root[x-1],root[y],1)]]>key)
            {

                printf("0\n");
            }
            else
            {
                int l=0,r=y-x+1;
                int ans=0,mid;
                while(l<=r)
                {
                    int mid=(l+r)/2;
                    if(d[id[query(1,n,root[x-1],root[y],mid)]]<=key)
                        l=mid+1,ans=mid;
                    else
                        r=mid-1;
                }
                printf("%d\n",ans);
            }
        }
    }
    return 0;


}


SPOJ COT Count on a tree

s=s(lson[u])+s(lson[v])-2*s(lson[lca])
记住如果lca 在[l,mid] 中 s要+1

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#define M 100005

using namespace std;

int g[M];
struct Edge
{
    int nxt,v;
} e[M*2];

struct Node
{
    int l,r,s;

} a[M*20];
vector<pair<int ,int > > q[M];
int cnt,num,key,n,m;
int p[M],fa[M],id[M],d[M],b[M],root[M];
int from[M],to[M],val[M];
void add(int u,int v)
{
    e[++cnt].nxt=g[u],e[cnt].v=v,g[u]=cnt;
    e[++cnt].nxt=g[v],e[cnt].v=u,g[v]=cnt;
}

void update(int &t,int l,int r)
{
    a[++num]=a[t];
    t=num;
    ++a[t].s;
    if(l==r)
        return ;
    int mid=(l+r)/2;
    if(key<=mid)
        update(a[t].l,l,mid);
    else
        update(a[t].r,mid+1,r);
}

int ifind(int x)
{
    return p[x] == x  ?  x : p[x]=ifind(p[x]);
}
bool vis[M];
int lca[M];

void dfs(int x)
{
   // cout<<x<<endl;
    p[x]=x;
    key=b[x];
    root[x]=root[fa[x]];
    update(root[x],1,n);
    for(int i=g[x]; i; i=e[i].nxt)
        if(e[i].v!=fa[x])
        {
            //cout<<e[i].v<<endl;
            fa[e[i].v]=x;
            dfs(e[i].v);
            p[e[i].v]=x;
        }
    vis[x]=1;
    int t=q[x].size();
    for(int i=0; i<t; ++i)
        if(vis[q[x][i].first])
        {
            lca[q[x][i].second]=ifind(q[x][i].first);
        }
}

bool cmp(int x,int y)
{
    return d[x]<d[y];


}

int getans(int l,int r,int x,int y,int f,int k)
{
    if(l==r)
        return l;
    int mid=(l+r)/2,s=a[a[x].l].s+a[a[y].l].s-(a[a[f].l].s<<1);
    if(b[key]>=l && b[key]<=mid)
        ++s;
    if(k<=s)
        return getans(l,mid,a[x].l,a[y].l,a[f].l,k);
    else
        return getans(mid+1,r,a[x].r,a[y].r,a[f].r,k-s);
}


int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
        scanf("%d",&d[i]),id[i]=i;
    sort(id+1,id+n+1,cmp);
    for(int i=1; i<=n; i++)
        b[id[i]]=i;
    for(int i=1,x,y; i<n; i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);
    }
    for(int i=1; i<=m; ++i)
    {
        scanf("%d%d%d",&from[i],&to[i],&val[i]);
        q[from[i]].push_back(pair<int, int> (to[i], i));
        q[to[i]].push_back(pair<int, int> (from[i], i));
    }
    dfs(1);
    for(int i=1; i<=m; ++i)
    {
        if(from[i]==to[i])
        {
            printf("%d\n", d[from[i]]);
            continue;
        }
        key=lca[i];
        printf("%d\n", d[id[getans(1, n, root[from[i]], root[to[i]], root[key], val[i])]]); //被root[ff]坑了一早上,写成了ff。唉
    }
    return 0;
}




主席树模板总结及题集 介绍篇:http://blog.youkuaiyun.com/metalseed/article/details/8045038  -> 理解篇(配图比较生动):http://blog.youkuaiyun.com/regina8023/article/details/41910615  -> 题目:poj2104 区间查询第k大元素,非递归写法,非递归不好进行回溯操作,递归更好写一些 #include #inc 阅读详情

相关推荐

动态主席树

写在前面 相对于静态主席树,动态主席树意味着,每个节点可能会修改称为新的值,按照我们平时的想法,一定是在之前要删除的位置上进行-1操作,然后再新插入的位置上+1 解析 静态主席树我们在每个节点处创建一个权值线段树,然后在区间[l,r]求解时,使用第r棵线段树 - 第l-1棵线段树,在这个线段树上进行查询第k大元素的离散位置,然后根据之前进行离散的结果,得到最终的位置 使用ZOJ-2112作...

A_Bo的博客 1082

主席树详解(基础)

可持久化线段树,又称主席树,本文详解它的构成和基础用法

nxhx_的博客 4661

ArcGIS 10.4 Desktop安装步骤。

步骤 1 :安装 LicenseManager 有了安装包以后,我们进入安装包文件目录,如图所示,首先需要安装ArcGIS license manager,即点击打开图中红色框中exe文件。 PS:安装 LicenseManager,关于 License 的安装路径一般默认即可,因为很小的,装C 盘也无所谓了,当然了自己改了也可以的,但是不建议! 即便修改路径,建议只改盘符,不修改相对路径方式! 如:C:\Program Files (x86)\ArcGIS\License10.6 修改为 D:\.

IT爱好者 2万+

主席树(POJ-2104、HDU-2665)

【算法分析】 主席树名称来源于其发明人黄嘉泰的姓名的首字母缩写HJT与我们某位主席姓名的首字母缩写一样。 主席树的经典应用在于求某个区间内的第K小/大数的值。比如区间第K大问题,就是给定一个数列a,询问给定区间[L,R]的第K大值。如对数列a=[4,1,3,2,5],针对询问L=2,R=5,K=2,其答案为2。 主席树是一种可持久化数据结构,即可持久化权值线段树。 为了实现可持久化,就要保存线...

hnjzsyjyj的专栏 3566

高通Camera PDAF调试实战:从Type2到Type3的避坑指南与Log分析技巧

本文深入解析高通Camera平台PDAF调试实战,重点对比Type2与Type3的核心差异,提供详细的配置迁移方案和Log分析技巧。针对常见兼容性问题如对焦速度变慢、低光失效等,给出具体解决方案,并分享性能优化案例与高级调试工具链,帮助开发者快速提升PDAF调试效率。

weixin_29164185的博客 411

CTFshow-pwn入门-前置基础pwn32-pwn34

CTFshow-pwn入门-前置基础pwn32-pwn34

你们de4月天的博客 1131

可持久化数据结构-线段树(主席树)

可持久化线段树的概念和简单运用

zje11的博客 2741

Allegro174版本如何关闭模块复用后铜皮自动从动态变成静态操作指导

在用Allegro进行PCB设计的时候,模块复用是使用的十分频繁的操作,当Allegro升级到了174 S034版本的时候,当使用模块复用的功能的时候,模块内的铜皮会自动动静转换,大部分情况是不需要的。版本如何关闭模块复用后铜皮自动从动态变成静态操作指导。如何关闭这个功能,具体操作如下。

weixin_54787054的博客 1259

主席树简介及应用

【主席树简介】 主席树,即可持久化线段树,又称函数式线段树,是重要的可持久化数据结构之一。所谓可持久化,是指可以回溯到历史版本。 主席树的本质,就是在有数据更新时,在基准线段树的基础上采用“结点复用”的方式仅仅增加少量结点来维护历史数据,而不是通过存储不同版本线段树的方式来维护历史数据,从而达到减少时空消耗的目的,避免出现TLE(Time Limit Exceeded)及MLE(Memory Limit Exceeded)错误。主席树空间一般建议是开n<<5(n为基准线段树的结点数)。 如在..

hnjzsyjyj的专栏 3313

AI人工智能与数据挖掘的技术融合趋势

我们的目的是搞清楚AI人工智能和数据挖掘是怎么融合在一起的,以及这种融合未来会有什么样的发展趋势。范围涵盖了这两种技术融合的原理、应用场景,还有未来可能面临的挑战。我们会先讲讲AI人工智能和数据挖掘是什么,它们之间有什么关系。然后说说它们融合的算法原理、数学模型。接着通过一个实际的项目案例,看看它们是怎么在实际中运用的。还会介绍一些它们的应用场景和相关工具。最后分析一下未来的发展趋势和挑战,并且总结学到的知识,提出一些思考题让大家思考。AI人工智能。

AI 领航者的博客 1367

Android 10.0 SystemUI 屏蔽状态栏消息推送弹出的悬浮通知

在状态栏中,有一些通知类似 消息推送 弹出的 悬浮通知,弹出30秒之后会消失掉 要想屏蔽掉这些通知,首选知道这些通知是怎么产生的 通知类型 NotificationContentInflater.java 详细的介绍各种通知的类型 frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java /** * The defau

安卓兼职framework和app工程师的博客 1542

主席树+可修改主席树

普通主席树 普通主席树比较简单 就是很多个权值线段树 每一次加进去log个节点(每层一个),剩下的节点用原来的线段树中的节点直接连到新节点上就好了 线段树 插入节点 主席树 主席树拆开之后 POJ2104 主席树模板题 代码: 1 #include<algorithm> 2 #include<cstdio&gt...

aozhuan8489的博客 258

【重温童年】基于tkinter模块设计的Q宠大乐斗武器升星模拟器:重温经典,畅享休闲时光

与传统的Q宠大乐斗不同,这款模拟器还加入了一个创新的功能——自定义升星概率。玩家可以根据自己的喜好和策略,为不同的武器设置不同的成功率和降级率。比如,你可以将“嗜血”这把武器的升星难度设置得极高,以体现其稀有性和强大威力;也可以将“平底锅”这样的普通武器设置得相对容易升星,让玩家在升级过程中感受到更多的成就感。这种自定义的概率设置,不仅增加了游戏的趣味性和挑战性,还让玩家在升级过程中有了更多的策略和选择。你可以根据自己的武器库和卷轴数量,制定出最合适的升级计划,从而在游戏中占据先机。

nmdbbzcl的博客 1237

关于主席树

什么是主席树? 主席树又叫做可持久化线段树,其实后者才是它的大名只是大家都图方便就叫前者了。 可持久化线段树,一听名字就知道它的两个终点:可持久化,线段树。 都要学主席树了,线段树是什么总归都知道的吧,那什么是可持久化呢? 可持久化理解起来其实也很简单,说白了就是可以查询历史节点就可以叫可持久化了,所以可持久化线段树的意思就是可以查询线段树的历史节点就是可持久化了。 如何实现可持久化? 我们这边先给出一棵线段树吧。 画的不好,大家理解一下就行了 假设说我现在想要单点修改最左边的叶子节点 在这里插入图片描述

two_big_monkey的博客 2141

rk3568 rk628桥片 rgb2hdmi

RK628 是瑞芯微全新推出的视频桥接芯片,支持丰富的显示接口,支持高分辨率大屏产品转换需求。基于DRM、FB的显示框架易于使用。 输入信号支持:HDMI、RGB、BT.1120,输出信号支持 HDMI、GVI、Dual LVDS、Dual MIPI、MIPI-CSI、RGB、BT.1120,最高支持4K 60fps 输入/输出转换,并且支持输入到输出 1/4~4倍的缩放。

weixin_35723192的博客 452

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

主席树介绍

函数式(现在又称主席式。。。)数据结构从来都没写过,感觉这个东西可以挖掘出不少东西出来,于是开一组专题。 先根据 Seter 留下的文本做一些记录。。 主席树大概是一种离线结构,我以前反正没看到过这东西,所以就自己给他起名字了!如果谁知道这东西的真名,请告诉我! 现在我们知道,主席树的全名应该是 函数式版本的线段树。加上附带的一堆 technology。。 。。

MetalSeed 4万+

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

待修主席树

废话 主席树入门那篇博客至今已经一年半了,然而我现在才写待修主席树。 网上很多人的待修主席树讲的不明白,往往是一句话带过,跟没说区别不大,大家上网搜资料学习当然都是想学的细致一点,那么对于写博客的人来说,自然要负起责任来写的详细一点。 希望这篇博客能给你帮助。 进入正题! 前置芝士——主席树入门。 以前的码风不优秀还请见谅qwq…… 在其他的博客里大家都能看到这样一句话: 普通的主席树记录的是...

a_forever_dream的博客 503

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

上一篇: bzoj 1034 n [ZJOI2008]泡泡堂BNB 贪心 田忌赛马
下一篇: Codeforces Round 307 Div 2
DJS_K_D
博客等级 码龄12年 2粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值