P2633 Count on a tree 主席樹求樹上第k大

看到樹上第k大 首先想想普通的前綴和怎麼做  假如我要靜態的求鏈(u,v)的和  那麼我們就從樹根一直搜下來 維護一個前綴和,答案就是 sum[u]+sum[v]-sum[lca(u,v)]-sum[fa[lc[u,v]]]

現在再來看主席樹的方法就一目瞭然啦 對於每一個結點 在父節點的基礎上建樹 然後詢問的時候

觀察 sum[lc[u]]+sum[lc[v]]-sum[lc[lca(u,v)]]-sum[lc[fa[lca(u,v)]]] 和k 的大小關係即可

#include<bits/stdc++.h>
#define I inline void
#define R register int
using namespace std;
const int N = 1e5+100;
int n,m;
int sum[N*40],lc[N*40],rc[N*40],rt[N],tot;
int fa[N][30],lg[N],dep[N];
int cur,h[N],nex[N<<1],to[N<<1];
int has[N],val[N],cnt;
inline int in(){
	int w=0,x=0;char c=0;
	while(c>'9'||c<'0') w|=c=='-',c=getchar();
	while(c<='9'&&c>='0') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return w?-x:x;
}
inline int gethas(int x){
	return lower_bound(has+1,has+1+cnt,x)-has;
}
I add_edge(R x,R y){
	to[++cur]=y;nex[cur]=h[x];h[x]=cur;
}
inline int lca(R x,R y){
	if(dep[x]<dep[y]) swap(x,y);
	while(dep[x]>dep[y]) x=fa[x][lg[dep[x]-dep[y]]-1];
	if(x==y) return x;
	for(int i = lg[dep[x]-1]; i >= 0; i--)
		if(fa[x][i]!=fa[y][i]) 
		x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}
void update(int &rt,R las,R l,R r,R pos){
	rt=++tot;
	sum[rt]=sum[las]+1;lc[rt]=lc[las];rc[rt]=rc[las];
	if(l==r) return;
	int mid = l+r>>1;
	if(pos<=mid) update(lc[rt],lc[las],l,mid,pos);
	else update(rc[rt],rc[las],mid+1,r,pos);
} 
int query(R u,R v,R lca,R flc,R l,R r,R k){
	if(l==r) return l;
	R g = sum[lc[u]]+sum[lc[v]]-sum[lc[lca]]-sum[lc[flc]];
	R mid = l+r>>1;
	if(k<=g) return query(lc[u],lc[v],lc[lca],lc[flc],l,mid,k);
	else return query(rc[u],rc[v],rc[lca],rc[flc],mid+1,r,k-g); 
}
void dfs(int u,int fath){
	fa[u][0]=fath,dep[u]=dep[fath]+1;
	for(int i = 1; i <= lg[dep[u]]; i++) 
	fa[u][i]=fa[fa[u][i-1]][i-1];
	update(rt[u],rt[fath],1,cnt,gethas(val[u]));
	for(int i = h[u]; i; i = nex[i]){
		int v = to[i];
		if(v==fath) continue;
		dfs(v,u);
	}
}
int main(){
	n=in(),m=in();
	for(R i = 1; i < N; i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
	for(R i = 1; i <= n; i++) 
	val[i]=in(),has[i]=val[i];
	sort(has+1,has+1+n);
	cnt=unique(has+1,has+1+n)-has;
	for(R i = 1; i <= n-1; i++){
		R u,v;
		u=in(),v=in();
		add_edge(u,v);add_edge(v,u);
	}
	dfs(1,0);
	int last=0;
	//printf("tot=%d cur=%d cnt=%d\n",tot,cur,cnt);
	for(R i = 1; i <= m; i++){
		R u,v,k;
		u=in(),v=in(),k=in();
		u^=last;
		int lcauv=lca(u,v);
		//printf("u=%d v=%d lcauv=%d\n",u,v,lcauv);
		last=has[query(rt[u],rt[v],rt[lcauv],rt[fa[lcauv][0]],1,cnt,k)];
		printf("%d\n",last);
	}
	return 0;
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章