• Subtree Minimum Query CodeForces


    题目链接:https://cn.vjudge.net/problem/CodeForces-893F

    题目大意:给你n个点,每一个点有权值,然后这n个点会构成一棵树,边权为1.然后有q次询问,每一次询问包括t1和t2。让你找出以t1为根节点的树上,距离t1不超过t2的节点,最小的点权值。

    每一次的t1是(上次询问的结果+t1)%n+1,t2是(上次询问的结果+t1)。所以就必须的强制在线了。

    具体思路:线段树合并,通过dfs序进行遍历,以每一个点的深度作为下标建树。一开始,每一个节点储存的是从当前节点到叶子节点的最小的值。但是题目中要求的是以当前节点为根节点的长度<=k的最小值,这个时候我们需要往上更新。这个更新过程就需要用到线段树合并了,把每一个子节点归并到他的父亲节点上,这样逐渐的往上递归就可以了,因为父亲节点要获取子节点的所有的信息。

    然后顺便学习了一下线段树的动态开点,这个过程有点像主席树的创建过程,并不是一开始就吧线段树建立好,而是用到哪个点就给这个点编号。

    这个题搞了一天才明白,,,感谢周恩杰的帮助([]~( ̄▽ ̄)~*)。

    AC代码:

      1 #include<iostream>
      2 #include<stack>
      3 #include<cmath>
      4 #include<stdio.h>
      5 #include<algorithm>
      6 #include<cstring>
      7 #include<queue>
      8 using namespace std;
      9 # define ll long long
     10 # define lson l,m,rt<<1
     11 # define rson m+1,r,rt<<1|1
     12 const int maxn = 2e5+100;
     13 # define inf 0x3f3f3f3f
     14 # define ll_inf 0x3f3f3f3f3f3f3f
     15 struct Edge{
     16 ll to,nex;
     17 }edge[maxn<<2];
     18 struct node{
     19 ll val;
     20 ll ch[3];
     21 void in(){val=ll_inf,ch[0]=ch[1]=0;}
     22 }q[maxn*40];
     23 ll head[maxn],num,depth[maxn],tot,n;
     24 ll root[maxn];
     25 ll a[maxn];
     26 void init(ll n){
     27 for(ll i=0;i<=n;i++){
     28 head[i]=-1;
     29 }
     30 num=0;
     31 tot=0;
     32 }
     33 void addedge(ll fr,ll to){
     34 edge[num].nex=head[fr];
     35 edge[num].to=to;
     36 head[fr]=num++;
     37 }
     38 #define lch     q[rt].ch[0]
     39 #define rch     q[rt].ch[1]
     40 void up(ll rt){
     41 q[rt].val=min(q[lch].val,q[rch].val);
     42 }
     43 void update(ll pos,ll val,ll l,ll r,ll &rt){
     44 q[rt=++tot].in();
     45 if(l==r){
     46 q[rt].val=val;
     47 return ;
     48 }
     49 ll mid=(l+r)>>1;
     50 if(pos<=mid)update(pos,val,l,mid,lch);
     51 else update(pos,val,mid+1,r,rch);
     52 up(rt);
     53 }
     54 ll merge(ll u,ll v){
     55 if(!v)return u;
     56 if(!u)return v;
     57 ll tmp=++tot;
     58 q[tmp].in();
     59 q[tmp].ch[0]=merge(q[u].ch[0],q[v].ch[0]);
     60 q[tmp].ch[1]=merge(q[u].ch[1],q[v].ch[1]);
     61 q[tmp].val=min(q[u].val,q[v].val);
     62 return tmp;//注意这个地方返回的是tmp,而不是tot。因为这个过程tot还会增加,而这个地方需要的是原来的tot,所以返回的是tmp
     63 }
     64 void dfs(ll u,ll fr,ll dep){
     65 depth[u]=dep;
     66 update(depth[u],a[u],1,n,root[u]);
     67 for(ll i=head[u];i!=-1;i=edge[i].nex){
     68 ll to=edge[i].to;
     69 if(to==fr)continue;
     70 dfs(to,u,dep+1);
     71 root[u]=merge(root[u],root[to]);
     72 }
     73 }
     74 ll query(ll L,ll R,ll l,ll r,ll x){
     75 if(r<L||l>R)return ll_inf;
     76 if(L<=l&&R>=r)return q[x].val;
     77 ll mid=(l+r)>>1;
     78 return min(query(L,R,l,mid,q[x].ch[0]),query(L,R,mid+1,r,q[x].ch[1]));
     79 }
     80 int main(){
     81 ll m,st,ed;
     82 scanf("%lld %lld",&n,&m);
     83 for(ll i=1;i<=n;i++){
     84 scanf("%lld",&a[i]);
     85 }
     86 init(n);
     87 for(ll i=2;i<=n;i++){
     88 scanf("%lld %lld",&st,&ed);
     89 addedge(st,ed);
     90 addedge(ed,st);
     91 }
     92 q[0].in();
     93 dfs(m,m,1);
     94 //for(int i=1;i<=n;i++){
     95 //cout<<i<<" "<<root[i]<<endl;
     96 //}
     97 ll Case=0,last=0;
     98 scanf("%lld",&Case);
     99 while(Case--){
    100 scanf("%lld %lld",&st,&ed);
    101 st=(last+st)%n+1;
    102 ed=(last+ed)%n;
    103 //cout<<depth[st]<<" "<<depth[st]+ed<<endl;
    104 last=query(depth[st],depth[st]+ed,1,n,root[st]);
    105 printf("%lld
    ",last);
    106 }
    107 return 0;
    108 }
  • 相关阅读:
    ElementUI Select下拉框定位问题!
    Vue2 中keyup.enter触发问题!
    Java编写1到100质数之和
    JSP过滤器、Session监听器、Servlet控制器的关系和执行顺序
    EL表达式读取属性不存在的异常,读取类的属性不存在,无法调用到该属性
    Servlet中使用request转发页面引发的500空指针异常
    JSP动态产生的代码,点击显示确认操作,根据操作跳转并传值。
    Linux常用命令大全
    FastAdmin
    Laravel入门
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10518427.html
Copyright © 2020-2023  润新知