CF893F Subtree Minimum Query

题目

这不线段树合并板子题吗

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
#define re register
#define maxn 100005
#define inf 9999999999
inline int read() {
	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
inline int max(int a,int b) {return a>b?a:b;}
inline int min(int a,int b) {return a<b?a:b;}
struct E{int v,nxt;}e[maxn<<1];
int l[maxn*40],r[maxn*40],mx[maxn*40];
int tot,rt[maxn];
int n,ro,head[maxn],num,md,deep[maxn],a[maxn];
inline void add(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
void dfs(int x) {
	md=max(md,deep[x]);
	for(re int i=head[x];i;i=e[i].nxt) {
		if(deep[e[i].v]) continue;
		deep[e[i].v]=deep[x]+1;
		dfs(e[i].v);
	}
}
inline void pushup(int now) {mx[now]=min(mx[l[now]],mx[r[now]]);}
int change(int now,int x,int y,int pos,int val) {
	if(!now) now=++tot,mx[now]=inf;
	if(x==y) {mx[now]=min(mx[now],val);return now;}
	int mid=x+y>>1;
	if(pos<=mid) l[now]=change(l[now],x,mid,pos,val);
		else r[now]=change(r[now],mid+1,y,pos,val);
	pushup(now);return now;
}
int merge(int a,int b,int x,int y) {
	if(!a) return b;if(!b) return a;
	int now=++tot;
	if(x==y) {mx[now]=min(mx[a],mx[b]);return now;}
	int mid=x+y>>1;
	l[now]=merge(l[a],l[b],x,mid),r[now]=merge(r[a],r[b],mid+1,y);
	pushup(now);return now;
}
int query(int now,int x,int y,int lx,int ry) {
	if(!now) return inf;
	if(x<=lx&&y>=ry) return mx[now];
	int mid=lx+ry>>1;
	if(y<=mid) return query(l[now],x,y,lx,mid);
	if(x>mid) return query(r[now],x,y,mid+1,ry);
	return min(query(l[now],x,y,lx,mid),query(r[now],x,y,mid+1,ry));
}
void Dfs(int x) {
	for(re int i=head[x];i;i=e[i].nxt) {
		if(deep[e[i].v]<deep[x]) continue;
		Dfs(e[i].v);
		rt[x]=merge(rt[x],rt[e[i].v],1,md);
	}
}
int main() {
	n=read(),ro=read();
	for(re int i=1;i<=n;i++) a[i]=read();
	for(re int x,y,i=1;i<n;i++) x=read(),y=read(),add(x,y),add(y,x);
	deep[ro]=1,dfs(ro);mx[0]=inf;
	for(re int i=1;i<=n;i++) rt[i]=change(rt[i],1,md,deep[i],a[i]);
	Dfs(ro);
	int x,y,Q=read(),lst=0;
	while(Q--) {
		x=read(),y=read();
		x+=lst;x%=n,x++;y+=lst;y%=n;
		lst=query(rt[x],deep[x],deep[x]+y,1,md);
		printf("%d\n",lst);
	}
	return 0;
}

或许我们还可以直接\(dsu\ on\ tree\),对\(dsu\)里的桶可持久化,这样就是空间时间都多一个\(log\)

主席树的做法巧妙的一批,我们可以以深度为时间轴,以\(dfs\)序为下标来建树

查询的时候直接查\([1,dep_x+k]\)\(dfn_x<=dfn<=dfn_x+sum_x-1\),由于\(dfn\)的限制,所以这样的点只会存在于\(x\)的子树里

posted @ 2019-03-15 19:38  asuldb  阅读(711)  评论(0编辑  收藏  举报