博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【洛谷2633】Count on a tree(树上主席树)
阅读量:4923 次
发布时间:2019-06-11

本文共 2863 字,大约阅读时间需要 9 分钟。

大致题意: 给你一棵树,每次问你两点之间第\(k\)小的点权,强制在线。

主席树

这种题目强制在线一般就是数据结构了。

而看到区间第\(k\)小,很容易就能想到。

至少不会有人想到树套树

树上主席树

与一般的主席树不同,这题的主席树是树上主席树(不过许多奆佬称其为主席树上树)。

维护数列的主席树,我们一般是由前一个数的主席树构造当前树的主席树。

而树上的主席树其实也是类似的,可以由父亲节点的主席树构造当前树的主席树。

关于查询操作

关于查询两个节点\(x,y\)路径间第\(k\)小的权值,我们进行如下操作:

  • 首先,找到\(x\)\(y\)\(LCA\),姑且命名它为\(z\)
  • 然后,我们可以进行差分,即用\(x\)\(y\)的值与\(z\)\(fa_z\)的值相减,就可以得出最终的答案(这与数组版的主席树是类似的)。

对于\(LCA\),我们可以直接用。

然后我们就可以发现这是一道主席树板子题。

代码

#include
#define max(x,y) ((x)>(y)?(x):(y))#define min(x,y) ((x)<(y)?(x):(y))#define uint unsigned int#define LL long long#define ull unsigned long long#define swap(x,y) (x^=y,y^=x,x^=y)#define abs(x) ((x)<0?-(x):(x))#define INF 1e9#define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))#define ten(x) (((x)<<3)+((x)<<1))#define N 100000#define LogN 20#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)using namespace std;int n,cnt,ee=0,a[N+5],p[N+5],lnk[N+5],Depth[N+5],fa[N+5][LogN+5];struct edge{ int to,nxt;}e[(N<<1)+5];class FIO{ private: #define Fsize 100000 #define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++) #define pc(ch) (FoutSize
=0;--i) if(fa[x][i]^fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0];}class Class_ChairmanTree//主席树{ private: int n,tot,Root[N+5]; struct Tree { int Val,Size,Son[2]; }node[N*LogN+5]; inline void Build(int l,int r,int &rt)//建树 { if(!rt&&(rt=++tot),!(l^r)) return; register int mid=l+r>>1; Build(l,mid,node[rt].Son[0]),Build(mid+1,r,node[rt].Son[1]); } inline void ins(int l,int r,int &rt,int lst,int val)//插入 { if(node[rt=++tot]=node[lst],++node[rt].Size,!(l^r)) return; register int mid=l+r>>1; val<=mid?ins(l,mid,node[rt].Son[0],node[lst].Son[0],val):ins(mid+1,r,node[rt].Son[1],node[lst].Son[1],val); } inline int qry(int l,int r,int rt1,int rt2,int rt3,int rt4,int k)//查询 { if(!(l^r)) return l; register int mid=l+r>>1,t=node[node[rt3].Son[0]].Size+node[node[rt4].Son[0]].Size-node[node[rt1].Son[0]].Size-node[node[rt2].Son[0]].Size; if(t>=k) return qry(l,mid,node[rt1].Son[0],node[rt2].Son[0],node[rt3].Son[0],node[rt4].Son[0],k); else return qry(mid+1,r,node[rt1].Son[1],node[rt2].Son[1],node[rt3].Son[1],node[rt4].Son[1],k-t); } public: inline void Init(int len) {Build(1,n=len,Root[0]);}//初始化 inline void Insert(int v,int nv,int val) {ins(1,n,Root[nv],Root[v],val);} inline int Query(int v1,int v2,int k) {return qry(1,n,Root[LCA(v1,v2)],Root[fa[LCA(v1,v2)][0]],Root[v1],Root[v2],k);}}ChairmanTree;inline int find(int x)//离散化{ register int l=1,r=cnt,mid=l+r>>1; for(;l<=r;mid=l+r>>1) p[mid]

转载于:https://www.cnblogs.com/chenxiaoran666/p/Luogu2633.html

你可能感兴趣的文章
ios中的coredata
查看>>
WPF控件库:文字按钮的封装
查看>>
N1 语法单词
查看>>
[转载]DIV CSS设计时IE6、IE7、FF 与兼容性有关的特性
查看>>
[zz]使用thrift做c++,java和python的相互调用
查看>>
使用debootstrap 命令
查看>>
folly 相关库学习
查看>>
PHP中magic_quotes_gpc动态关闭无效的问题
查看>>
(转)使用NuGet管理项目库
查看>>
17行为型模式之命令模式
查看>>
mac 下快捷键
查看>>
假期作业6-10
查看>>
50-02 字符流中第一个不重复的字符( 时间空间效率的平衡)
查看>>
position中static、relative、absolute、fixed的分析
查看>>
computer专业术语总结
查看>>
为Google Reader守夜。。。
查看>>
20165235我期望的师生关系
查看>>
【转载】C++中的static关键字的总结
查看>>
虚拟机安装Windwos8,实现与Windows7双启动
查看>>
搭建ftp服务器
查看>>