Processing math: 100%

CF893F:Subtree Minimum Query(线段树合并)

Description

给你一颗有根树,点有权值,m次询问,每次问你某个点的子树中距离其不超过k的点的权值的最小值。(边权均为1,点权有可能重复,k值每次询问有可能不同,强制在线

Input

第一行两个数,为点数n和树根r
第二行n个数,为每个点的权值。
后面n1行给出树边
再一行m,后面给出m组询问。

Output

一行答案。

Sample Input

5 2
1 3 2 3 5
2 3
5 1
3 4
4 1
2
1 2
2 3

Sample Output

2

5

Solution

线段树合并板子题。注意数组大小QAQ我老是开小RE……

感觉Slrberetty两个人数据结构学傻了用了另一个题非常麻烦的做法写的这个题……

Code

复制代码
 1 #include<iostream>
 2 #include<cstdio>
 3 #define N (100009)
 4 using namespace std;
 5 
 6 struct Sgt{int ls,rs,min;}Segt[N<<6];
 7 struct Edge{int to,next;}edge[N<<1];
 8 int n,m,sgt_num,ans,lastans,u,v,p,q,r;
 9 int a[N],Root[N],Depth[N];
10 int head[N],num_edge;
11 
12 void add(int u,int v)
13 {
14     edge[++num_edge].to=v;
15     edge[num_edge].next=head[u];
16     head[u]=num_edge;
17 }
18 
19 void Update(int &now,int l,int r,int x,int v)
20 {
21     if (!now) now=++sgt_num;
22     Segt[now].min=2e9;
23     if (l==r) {Segt[now].min=v; return;}
24     int mid=(l+r)>>1;
25     if (x<=mid) Update(Segt[now].ls,l,mid,x,v);
26     else Update(Segt[now].rs,mid+1,r,x,v);
27     int ls=Segt[now].ls, rs=Segt[now].rs;
28     Segt[now].min=min(Segt[ls].min,Segt[rs].min);
29 }
30 
31 int Merge(int x,int y)
32 {
33     if (!x || !y) return x|y;
34     int tmp=++sgt_num;
35     Segt[tmp].ls=Merge(Segt[x].ls,Segt[y].ls);
36     Segt[tmp].rs=Merge(Segt[x].rs,Segt[y].rs);
37     Segt[tmp].min=min(Segt[x].min,Segt[y].min);
38     return tmp;
39 }
40 
41 void DFS(int x,int fa)
42 {
43     Depth[x]=Depth[fa]+1;
44     Update(Root[x],1,n,Depth[x],a[x]);
45     for (int i=head[x]; i; i=edge[i].next)
46         if (edge[i].to!=fa)
47         {
48             DFS(edge[i].to,x);
49             Root[x]=Merge(Root[x],Root[edge[i].to]);
50         }
51 }
52 
53 int Query(int now,int l,int r,int l1,int r1)
54 {
55     if (l>r1 || r<l1) return 2e9;
56     if (l1<=l && r<=r1) return Segt[now].min;
57     int mid=(l+r)>>1, ls=Segt[now].ls, rs=Segt[now].rs;
58     return min(Query(ls,l,mid,l1,r1),Query(rs,mid+1,r,l1,r1));
59 }
60 
61 int main()
62 {
63     Segt[0].min=2e9;
64     scanf("%d%d",&n,&r);
65     for (int i=1; i<=n; ++i)
66         scanf("%d",&a[i]);
67     for (int i=1; i<=n-1; ++i)
68     {
69         scanf("%d%d",&u,&v);
70         add(u,v); add(v,u);
71     }
72     DFS(r,0);
73     scanf("%d",&m);
74     for (int i=1; i<=m; ++i)
75     {
76         scanf("%d%d",&p,&q);
77         p=(p+lastans)%n+1; q=(q+lastans)%n;
78         ans=Query(Root[p],1,n,Depth[p],Depth[p]+q);
79         printf("%d\n",ans); lastans=ans;
80     }
81 }
复制代码
posted @   Refun  阅读(521)  评论(0编辑  收藏  举报
编辑推荐:
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
阅读排行:
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· Vite CVE-2025-30208 安全漏洞
· 《HelloGitHub》第 108 期
· MQ 如何保证数据一致性?
· 一个基于 .NET 开源免费的异地组网和内网穿透工具
点击右上角即可分享
微信分享提示