zoukankan      html  css  js  c++  java
  • [ SPOJ PT07J ] Query on a tree III

    (\)

    Description


    其实这题才是正版的 Qtree3......

    给定 (n) 个点,以 (1) 号节点为根的树,点有点权。

    (m) 次询问 以 (x) 为根的子树内,点权第 (k) 小的 节点编号 是多少。

    有多组测试数据,每组数据以 (DONE) 结尾。

    • (n,mle 10^5)

    (\)

    Solution


    注意到一棵树的子树 (DFS) 序是连续的。

    一遍 (DFS) 确定 (DFS) 序以及各个点的子树大小。

    (DFS) 序上建主席树就可以了。

    查子树查的其实就是 ((dfn[x]-1,dfn[x]+size[x]-1])

    注意查的是点的编号,但是注意到点权两两不同,就可以离散化后记录每一个点权对应的节点编号了。

    主席树注意空间 开成17倍成功RE

    (\)

    Code


    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 100010
    #define gc getchar
    #define Rg register
    #define mid ((l+r)>>1)
    using namespace std;
    
    inline int rd(){
      int x=0; bool f=0; char c=gc();
      while(!isdigit(c)){if(c=='-')f=1;c=gc();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
      return f?-x:x;
    }
    
    int n,m,tot,hd[N],val[N],tmp[N],len;
    
    struct edge{int to,nxt;}e[N<<1];
    
    inline void add(int u,int v){
      e[++tot].to=v; e[tot].nxt=hd[u]; hd[u]=tot;
    }
    
    int cnt,dfn[N],sz[N],vpos[N],pos[N];
    
    void dfs(int u,int fa){
      sz[u]=1;
      dfn[u]=++cnt;
      vpos[cnt]=val[u];
      for(Rg int i=hd[u],v;i;i=e[i].nxt)
        if((v=e[i].to)!=fa){dfs(v,u);sz[u]+=sz[v];}
    }
    
    struct seg{
    
      int rot[N],ptr;
    
      inline int newnode(){return ++ptr;}
    
      struct node{int ls,rs,sum;}c[N*20];
    
      void build(int &rt,int l,int r){
        rt=newnode();
        if(l==r) return;
        build(c[rt].ls,l,mid);
        build(c[rt].rs,mid+1,r);
      }
    
      inline void pushup(int rt){
        c[rt].sum=c[c[rt].ls].sum+c[c[rt].rs].sum;
      }
    
      void insert(int &rt,int lst,int l,int r,int x){
        rt=newnode();
        if(l==r){c[rt].sum=c[lst].sum+1;return;}
        if(x<=mid){
          c[rt].rs=c[lst].rs;
          insert(c[rt].ls,c[lst].ls,l,mid,x);
        }
        else{
          c[rt].ls=c[lst].ls;
          insert(c[rt].rs,c[lst].rs,mid+1,r,x);
        }
        pushup(rt);
      }
    
      inline int query(int rtl,int rtr,int l,int r,int k){
        if(l==r) return l;
        int nowans=c[c[rtr].ls].sum-c[c[rtl].ls].sum;
        if(k<=nowans) return query(c[rtl].ls,c[rtr].ls,l,mid,k);
        else return query(c[rtl].rs,c[rtr].rs,mid+1,r,k-nowans);
      }
    
    }tree;
    
    int main(){
      n=rd();
      for(Rg int i=1;i<=n;++i) tmp[i]=val[i]=rd();
      sort(tmp+1,tmp+1+n);
      for(Rg int i=1;i<=n;++i){
        tmp[++len]=tmp[i];
        while(tmp[i+1]==tmp[i]) ++i;
      }
      for(Rg int i=1;i<=n;++i){
        val[i]=lower_bound(tmp+1,tmp+1+len,val[i])-tmp;
        pos[val[i]]=i;
      }
      for(Rg int i=1,u,v;i<n;++i){
        u=rd(); v=rd(); add(u,v); add(v,u);
      }
      dfs(1,0);
      tree.build(tree.rot[0],1,len);
      for(Rg int i=1;i<=n;++i) tree.insert(tree.rot[i],tree.rot[i-1],1,len,vpos[i]);
      m=rd();
      for(Rg int i=1,rt,k;i<=m;++i){
        rt=rd(); k=rd();
        printf("%d
    ",pos[tree.query(tree.rot[dfn[rt]-1],tree.rot[dfn[rt]+sz[rt]-1],1,len,k)]);
      }
      return 0;
    }
    
    
  • 相关阅读:
    SignalR的三个Demo
    SignalR的一点点东西
    如何在appconfig中配置服务的ip
    IP分片丢失重传
    以太网之物理层
    以太网数据格式与封装解封
    OSI七层模型与TCP/IP五层模型
    边沿检测方法-FPGA入门教程
    如何用ModelsimSE仿真IP核-以PLL为例
    搭建Modelsim SE仿真环境-使用do文件仿真
  • 原文地址:https://www.cnblogs.com/SGCollin/p/9906062.html
Copyright © 2011-2022 走看看