Codeforces893F_Subtree Minimum Query

题意

给定一棵树和根,每个点有点权,强制在线询问\(x\)子树里离\(x\)距离不超过\(k\)的最小点权。

分析

  • 权值线段树合并的套路题,dfs,以深度作为下标,点权作为值,对每个点建立一颗权值线段树,然后回溯的时候合并到父节点的线段树上。
  • 合并时维护最小值,查询时也是查询区间最小值。
  • 内存给得多的情况下数组往死里开,不要白白送一发RE。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=6e5+50;
const int INF=0x3f3f3f3f;
vector<int> g[N];
int a[N],n,rt,u,v,lst,q,x,k;
int mn[N*30],ls[N*30],rs[N*30],tot,dep[N],tr[N];
void insert(int &rt,int l,int r,int p,int v){
    if(!rt){
        rt=++tot;
    }
    mn[rt]=v;
    int mid=(l+r)/2;
    if(l<r){
        if(p<=mid){
            insert(ls[rt],l,mid,p,v);
        }else{
            insert(rs[rt],mid+1,r,p,v);
        }
    }
}
int merge(int a,int b){
    if(!a || !b){
        return a+b;
    }
    int rt=++tot;
    mn[rt]=min(mn[a],mn[b]);
    ls[rt]=merge(ls[a],ls[b]);
    rs[rt]=merge(rs[a],rs[b]);
    return rt;
}
int query(int rt,int l,int r,int ql,int qr){
    if(!rt){
        return INF;
    }
    if(ql<=l && qr>=r){
        return mn[rt];
    }
    int ans=INF;
    int mid=(l+r)/2;
    if(ql<=mid){
        ans=min(ans,query(ls[rt],l,mid,ql,qr));
    }
    if(qr>mid){
        ans=min(ans,query(rs[rt],mid+1,r,ql,qr));
    }
    return ans;
}
void debug(int rt,int l,int r){
    printf("%d %d %d\n",l,r,mn[rt]);
    if(l==r){
        return;
    }
    int mid=(l+r)/2;
    debug(ls[rt],l,mid);
    debug(rs[rt],mid+1,r);
}
void dfs(int u,int f){
    dep[u]=dep[f]+1;
    insert(tr[u],1,n,dep[u],a[u]);
    int siz=g[u].size();
    for(int i=0;i<siz;i++){
        int v=g[u][i];
        if(v==f){
            continue;
        }
        dfs(v,u);
        tr[u]=merge(tr[u],tr[v]);
    }
}
int solve(int x,int k){
    return query(tr[x],1,n,dep[x],dep[x]+k);
}
int main(){
//    freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&rt);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(rt,0);
    scanf("%d",&q);
    while(q--){
        scanf("%d%d",&x,&k);
        x=(x+lst)%n+1;
        k=(k+lst)%n;
        printf("%d\n",lst=solve(x,k));
    }
    return 0;
}
全部评论

相关推荐

不愿透露姓名的神秘牛友
07-15 17:46
暑期就挂了,秋招还有机会吗
大聪明777:研发提前批,14号刚开的,官网上面的配图上有写。提前批没过的话,秋招还可以投,不过前面的笔试/面试记录会被保留,供秋招参考
26届校招投递进展
点赞 评论 收藏
分享
Twilight_m...:表格简历有点难绷。说说个人看法: 1.个人基本情况里好多无意义信息,什么婚姻状况、健康状况、兴趣爱好、户口所在地、身份证号码、邮政编码,不知道的以为你填什么申请表呢。 2.校内实践个人认为对找工作几乎没帮助,建议换成和测开有关的项目,实在没得写留着也行。 3.工作经历完全看不出来是干什么的,起码看着和计算机没啥关系,建议加强描述,写点你在工作期间的实际产出、解决了什么问题。 4.个人简述大而空,看着像AI生成,感觉问题最大。“Python,C,C++成为我打造高效稳定服务的得力工具”、“我渴望凭借自身技术知识与创新能力,推动人工智能技术的应用发展,助力社会实现智能化转型”有种小学作文的美感。而且你确定你个人简述里写的你都会嘛?你AI这块写的什么“深入研究”,发几篇顶会的硕博生都不一定敢这么写。而且你AI这块的能力和软测也完全无关啊。个人简述建议写你对哪些技术栈、哪些语言、哪些生产工具的掌握,写的有条理些,而且最好是和测开强相关的。
点赞 评论 收藏
分享
07-07 17:06
已编辑
深圳技术大学 golang
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务