博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SPOJ Count on a tree 主席树+lca
阅读量:4698 次
发布时间:2019-06-09

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

题意:给你一棵树,询问u到v路径上的第k大

题解:从u到v的路径能想到,u到根+v到根-lca(u,v)到根-fa[lca(u,v)]到根剩下的就是u到v之间的路径。因此只要离散化一下,每次dfs的时候处理倍增lca和主席树更新操作就可以

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//CLOCKS_PER_SEC#define se second#define fi first#define ll long long#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define Pii pair
#define Pli pair
#define ull unsigned long long#define pb push_back#define fio ios::sync_with_stdio(false);cin.tie(0)const double Pi=3.14159265;const int N=1e5+10;const ull base=163;const int INF=0x3f3f3f3f;using namespace std;int n,m, root[N], a[N],cnt=0;struct node { int l,r,sum;}T[40*N];int New[N];int fa[N][20];int dep[N];vector
v;int head[N],to[2*N],nx[2*N],tot=1;void add(int u,int v){ to[tot]=v; nx[tot]=head[u]; head[u]=tot++;}int getid(int x){ return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}void update(int l,int r,int &x,int y,int pos){ T[++cnt]=T[y],T[cnt].sum++,x=cnt; if(l==r)return ; int m=(l+r)>>1; if(pos<=m)update(l,m,T[x].l,T[y].l,pos); else update(m+1,r,T[x].r,T[y].r,pos);}void dfs(int u,int pre){ fa[u][0]=pre; dep[u]=dep[pre]+1; update(1,n,root[u],root[pre],New[u]); for(int i=1;i<17;i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; } for(int i=head[u];i;i=nx[i]){ int v=to[i]; if(pre==v)continue; dfs(v,u); }}int LCA(int u,int v){ if(dep[u]
=0;i--){ if(fa[v][i]!=fa[u][i]){ u=fa[u][i]; v=fa[v][i]; } } return fa[u][0];}int query(int l,int r,int k,int x,int y,int z,int w){ if(l==r)return l; int m=(l+r)>>1; int d=T[T[x].l].sum+T[T[y].l].sum-T[T[z].l].sum-T[T[w].l].sum; if(d>=k)return query(l,m,k,T[x].l,T[y].l,T[z].l,T[w].l); else return query(m+1,r,k-d,T[x].r,T[y].r,T[z].r,T[w].r);}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]),v.pb(a[i]); sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end()); for(int i=1;i<=n;i++)New[i]=getid(a[i]); for(int i=1;i<=n-1;i++){ int u,v;scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs(1,0); for(int i=1;i<=m;i++){ int l,r,k; scanf("%d%d%d",&l,&r,&k); printf("%d\n",v[query(1,n,k,root[l],root[r],root[LCA(l,r)],root[fa[LCA(l,r)][0]])-1]); } return 0;}

 

转载于:https://www.cnblogs.com/Mrleon/p/9097900.html

你可能感兴趣的文章
Windows 10正式版的历史版本
查看>>
hdu4057Rescue the Rabbit(ac自动机+dp)
查看>>
五个实用又有趣的网站
查看>>
靠写代码赚钱的一些门路
查看>>
将博客搬至CSDN
查看>>
Java 内存模型详解
查看>>
并发之初章Java内存模型
查看>>
ThreadLocal可以解决并发问题吗?
查看>>
1011 Sticks
查看>>
poj 3373 Changing Digits
查看>>
CROC-MBTU 2012, Elimination Round (ACM-ICPC) E. Mishap in Club
查看>>
爬虫抓取表格中的数据
查看>>
redis-3.0.0_rc5的RPM包制定
查看>>
JQuery Ajax 全解析
查看>>
Jfinal集成Spring
查看>>
JQuery操作class
查看>>
【easy】101. Symmetric Tree
查看>>
Android 4.0 NDK Updated
查看>>
第六次评分
查看>>
SAP FI配置步骤
查看>>