[CF893F]Subtree Minimum Query

题目大意:

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

做法跟HDU那道题一样,开两颗线段树,一颗维护每个深度最小值,一颗维护每个值所在最低深度,合并第二个线段树的时候顺便修改第一个即可

代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #define M 100010
 6 using namespace std;
 7 int n,m,num,cnt,top,r,ans;
 8 int head[M],a[M],b[M],rt1[M],rt2[M],deep[M];
 9 int val[M<<8],ch[M<<8][2];
10 struct point{int to,next;}e[M<<1];
11 void add(int from,int to) {
12     e[++num].next=head[from];
13     e[num].to=to;
14     head[from]=num;
15 }
16 int get(int x) {
17     int l=1,r=top;
18     while(l<=r) {
19         int mid=(l+r)/2;
20         if(b[mid]==x) return mid;
21         if(b[mid]>x) r=mid-1;
22         else l=mid+1; 
23     }
24 }
25 int insert(int rt,int l,int r,int x,int v) {
26     int node=++cnt;val[node]=min(val[rt],v);
27     if(l==r) return node;
28     int mid=(l+r)/2;
29     ch[node][0]=ch[rt][0],ch[node][1]=ch[rt][1];
30     if(x<=mid) ch[node][0]=insert(ch[rt][0],l,mid,x,v);
31     else ch[node][1]=insert(ch[rt][1],mid+1,r,x,v);
32     return node;
33 }
34 int merge1(int x,int y,int l,int r) {
35     if(!x||!y) return x+y;
36     int node=++cnt,mid=(l+r)/2;
37     val[node]=min(val[x],val[y]);
38     if(l==r) return node;
39     ch[node][0]=merge1(ch[x][0],ch[y][0],l,mid);
40     ch[node][1]=merge1(ch[x][1],ch[y][1],mid+1,r);
41     return node;
42 }
43 int merge2(int x,int y,int l,int r,int id) {
44     if(!x||!y) return x+y;
45     int node=++cnt,mid=(l+r)/2;
46     if(l==r) {
47         val[node]=min(val[x],val[y]);
48         rt1[id]=insert(rt1[id],1,n,val[node],l);
49         return node;
50     }
51     ch[node][0]=merge2(ch[x][0],ch[y][0],l,mid,id);
52     ch[node][1]=merge2(ch[x][1],ch[y][1],mid+1,r,id);
53     return node;
54 }
55 int query(int node,int l,int r,int l1,int r1) {
56     if(l1<=l&&r1>=r) return val[node];
57     int mid=(l+r)/2,ans=1e9;
58     if(l1<=mid) ans=min(ans,query(ch[node][0],l,mid,l1,r1));
59     if(r1>mid) ans=min(ans,query(ch[node][1],mid+1,r,l1,r1));
60     return ans;
61 }
62 void dfs(int x,int fa) {
63     deep[x]=deep[fa]+1;
64     rt1[x]=insert(0,1,n,deep[x],a[x]);
65     rt2[x]=insert(0,1,n,a[x],deep[x]);
66     for(int i=head[x];i;i=e[i].next)
67         if(e[i].to!=fa) {
68             dfs(e[i].to,x);
69             rt1[x]=merge1(rt1[x],rt1[e[i].to],1,n);
70             rt2[x]=merge2(rt2[x],rt2[e[i].to],1,n,x);
71         }
72 }
73 int main() {
74     memset(val,1,sizeof(val));
75     scanf("%d%d",&n,&r);
76     for(int i=1;i<=n;i++) 
77         scanf("%d",&a[i]),b[++top]=a[i];
78     sort(b+1,b+1+top);top=unique(b+1,b+1+top)-b-1;
79     for(int i=1;i<=n;i++) a[i]=get(a[i]);
80     for(int i=1;i<n;i++) {
81         int a,b;scanf("%d%d",&a,&b);
82         add(a,b),add(b,a);
83     }
84     dfs(r,0);scanf("%d",&m);
85     for(int i=1;i<=m;i++) {
86         int x,k;scanf("%d%d",&x,&k);
87         x=(x+ans)%n+1,k=(k+ans)%n;
88         printf("%d\n",ans=b[query(rt1[x],1,n,deep[x],min(deep[x]+k,n))]);
89     }
90     return 0;
91 }

 

转载于:https://www.cnblogs.com/Slrslr/p/10032935.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值