CF893F Subtree Minimum Query(主席树)

我们发现要求的答案是depth[u]-min(depth[u]+k,mx)之间的属于他子树的最小值,mx是最深的深度

在线算法,不难想到用主席树对深度建树,这样就可以求取区间深度的信息,区间min没有可减性,但是并不影响本题做法

因为我们只需要查找指定dfs序区间中的答案即可,这样才是他子树中的答案,在前缀的深度当中,只有子树的答案才会被用来更新

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=2e5+10;
const int mod=1e9+7;
int rt[N];
int a[N];
int depth[N];
int st[N],ed[N],times;
int h[N],ne[N],e[N],idx;
vector<int> num[N];
int mx;
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
struct node{
    int l,r;
    int mi;
}tr[N*30];
void dfs(int u,int fa){
    int i;
    st[u]=++times;
    num[depth[u]].push_back(u);
    mx=max(mx,depth[u]);
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(j==fa)
            continue;
        depth[j]=depth[u]+1;
        dfs(j,u);
    }
    ed[u]=times;
}
void build(int &p,int l,int r){
    p=++idx;
    tr[p].mi=1e9;
    if(l==r)
        return ;
    int mid=l+r>>1;
    build(tr[p].l,l,mid);
    build(tr[p].r,mid+1,r);
}
void insert(int &p,int q,int l,int r,int pos,int x){
    p=++idx;
    tr[p]=tr[q];
    tr[p].mi=min(tr[p].mi,x);
    if(l==r)
        return ;
    int mid=l+r>>1;
    if(pos<=mid)
        insert(tr[p].l,tr[q].l,l,mid,pos,x);
    else
        insert(tr[p].r,tr[q].r,mid+1,r,pos,x);
}
int query(int p,int l,int r,int L,int R){
    if(L<=l&&R>=r){
        return tr[p].mi;
    }
    int mid=l+r>>1;
    int ans=1e9;
    if(L<=mid)
        ans=min(ans,query(tr[p].l,l,mid,L,R));
    if(R>mid)
        ans=min(ans,query(tr[p].r,mid+1,r,L,R));
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    int i;
    int n,p;
    cin>>n>>p;
    memset(h,-1,sizeof h);
    for(i=1;i<=n;i++){
        cin>>a[i];
    }
    for(i=1;i<n;i++){
        int x,y;
        cin>>x>>y;
        add(x,y);
        add(y,x);
    }
    depth[p]=1;
    dfs(p,-1);
    build(rt[0],1,n);
    for(i=1;i<=mx;i++){
        rt[i]=rt[i-1];
        for(auto x:num[i])
        insert(rt[i],rt[i],1,n,st[x],a[x]);
    }
    int last=0;
    int m;
    cin>>m;
    while(m--){
        int p,q;
        cin>>p>>q;
        int x=(p+last)%n+1;
        int k=(q+last)%n;
        last=query(rt[min(depth[x]+k,mx)],1,n,st[x],ed[x]);
        cout<<last<<endl;
    }
    return 0;
}
View Code

 

posted @ 2020-12-07 22:49  朝暮不思  阅读(296)  评论(0编辑  收藏  举报