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\)的子树里

猜你喜欢

转载自www.cnblogs.com/asuldb/p/10539111.html
今日推荐