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


    Description

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

    Input

    第一行两个数,为点数$n$和树根$r$。
    第二行$n$个数,为每个点的权值。
    后面$n-1$行给出树边
    再一行$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$……

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

    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
    ",ans); lastans=ans;
    80     }
    81 }
  • 相关阅读:
    UVALive 4764 简单dp水题(也可以暴力求解)
    poj 2151 概率DP(水)
    poj 2299 归并排序求逆序数 (可做模板)
    poj2388 更水
    poj1936 假期计划第一水
    poj 3080 kmp求解多个字符串的最长公共字串,(数据小,有点小暴力 16ms)
    UVA315:Network(求割点)
    POJ1236:Network of Schools (思维+Tarjan缩点)
    SPOJ
    HDU4305:Lightning(生成树计数+判断点是否在线段上)
  • 原文地址:https://www.cnblogs.com/refun/p/10060147.html
Copyright © 2020-2023  润新知