2 条题解

  • 0
    @ 2025-10-8 17:06:46

    C55 可持久化线段树+LCA P2633 Count on a tree

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N=100005;
    #define mid ((l+r)>>1)
    int h[N],to[N*2],ne[N*2],idx; //邻接表
    void add(int a,int b){
      to[++idx]=b; ne[idx]=h[a]; h[a]=idx;
    }
    int n,m,bn,last,a[N],b[N]; //b:离散化数组
    int f[N][20],dep[N];       //LCA数组
    int rt[N],tot;             //根节点,开点个数
    int ls[N*20],rs[N*20],sum[N*20]; //可持久化线段树
    
    void change(int &u,int v,int l,int r,int p){ //点修
      u=++tot; //动态开点
      ls[u]=ls[v]; rs[u]=rs[v]; sum[u]=sum[v]+1;
      if(l==r) return;     //双指针同步搜索
      if(p<=mid) change(ls[u],ls[v],l,mid,p);
      else change(rs[u],rs[v],mid+1,r,p);
    }
    void dfs(int u,int fa){ //预处理
      change(rt[u],rt[fa],1,bn,a[u]); //建可持久线段树
      dep[u]=dep[fa]+1; f[u][0]=fa;
      for(int i=1; i<=18; i++) 
        f[u][i]=f[f[u][i-1]][i-1]; 
      for(int i=h[u];i;i=ne[i])
        if(to[i]!=fa) dfs(to[i],u);
    }
    int LCA(int u,int v){ //返回LCA
      if(dep[u]<dep[v]) swap(u,v);
      for(int i=18; i>=0; i--)
        if(dep[f[u][i]]>=dep[v]) u=f[u][i];
      if(u==v) return u;
      for(int i=18; i>=0; i--)
        if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
      return f[u][0];
    }
    int query(int u,int v,int x,int y,int l,int r,int k){ //点查
      if(l==r) return l;              //四指针同步搜索
      int s=sum[ls[u]]+sum[ls[v]]-sum[ls[x]]-sum[ls[y]];
      if(k<=s)return query(ls[u],ls[v],ls[x],ls[y],l,mid,k);
      else return query(rs[u],rs[v],rs[x],rs[y],mid+1,r,k-s);
    }
    int main(){
      scanf("%d%d",&n,&m); int u,v,k;
      for(int i=1;i<=n;++i)scanf("%d",&a[i]),b[i]=a[i];
      for(int i=1;i<n;++i)scanf("%d%d",&u,&v),add(u,v),add(v,u);
      sort(b+1,b+n+1);
      bn=unique(b+1,b+n+1)-b-1; //去重
      for(int i=1;i<=n;i++)
        a[i]=lower_bound(b+1,b+1+bn,a[i])-b; //离散值
      dfs(1,0); //预处理
      for(int i=1; i<=m; ++i){
        scanf("%d%d%d",&u,&v,&k); u^=last;
        int L=LCA(u,v);
        last=b[query(rt[u],rt[v],rt[L],rt[f[L][0]],1,bn,k)];
        printf("%d\n",last);
      }
    }
    
    • 0
      @ 2025-10-8 17:06:31

      C55 可持久化线段树+LCA P2633 Count on a tree

      #include <iostream>
      #include <cstring>
      #include <algorithm>
      using namespace std;

      const int N=100005; #define mid ((l+r)>>1) int h[ N],to[ N2],ne[ N2],idx; //邻接表 void add(int a,int b){ to[ ++idx]=b,ne[ idx]=h[ a],h[ a]=idx; } int n,m,bn,last,a[ N],b[ N]; //b:离散化数组 int f[ N][ 20],dep[ N]; //LCA数组 int rt[ N],tot; //根节点,开点个数 int ls[ N20],rs[ N20],sum[ N*20]; //可持久化线段树

      void change(int &u,int v,int l,int r,int p){ //点修 u=++tot; //动态开点 ls[ u]=ls[ v]; rs[ u]=rs[ v]; sum[ u]=sum[ v]+1; if(lr) return; //双指针同步搜索 if(p<=mid) change(ls[ u],ls[ v],l,mid,p); else change(rs[ u],rs[ v],mid+1,r,p); } void dfs(int u,int fa){ //预处理 change(rt[ u],rt[ fa],1,bn,a[ u]); //建可持久线段树 dep[ u]=dep[ fa]+1; f[ u][ 0]=fa; for(int i=1; i<=18; i++) f[ u][ i]=f[ f[ u][ i-1]][ i-1]; for(int i=h[ u];i;i=ne[ i]) if(to[ i]!=fa) dfs(to[ i],u); } int LCA(int u,int v){ //返回LCA if(dep[ u]<dep[ v]) swap(u,v); for(int i=18; i>=0; i--) if(dep[ f[ u][ i]]>=dep[ v]) u=f[ u][ i]; if(uv) return u; for(int i=18; i>=0; i--) if(f[ u][ i]!=f[ v][ i]) u=f[ u][ i],v=f[ v][ i]; return f[ u][ 0]; } int query(int u,int v,int x,int y,int l,int r,int k){ //点查 if(l==r) return l; //四指针同步搜索 int s=sum[ ls[ u]]+sum[ ls[ v]]-sum[ ls[ x]]-sum[ ls[ y]]; if(k<=s)return query(ls[ u],ls[ v],ls[ x],ls[ y],l,mid,k); else return query(rs[ u],rs[ v],rs[ x],rs[ y],mid+1,r,k-s); } int main(){ scanf("%d%d",&n,&m); int u,v,k; for(int i=1;i<=n;++i)scanf("%d",&a[ i]),b[ i]=a[ i]; for(int i=1;i<n;++i)scanf("%d%d",&u,&v),add(u,v),add(v,u); sort(b+1,b+n+1); bn=unique(b+1,b+n+1)-b-1; //去重 for(int i=1;i<=n;i++) a[ i]=lower_bound(b+1,b+1+bn,a[ i])-b; //离散值 dfs(1,0); //预处理 for(int i=1; i<=m; ++i){ scanf("%d%d%d",&u,&v,&k); u^=last; int L=LCA(u,v); last=b[ query(rt[ u],rt[ v],rt[ L],rt[ f[ L][ 0]],1,bn,k)]; printf("%d\n",last); } }</pre>

      • 1

      C55【可持久化线段树】树上路径第k小点[SPOJ10628]Count on a tree

      信息

      ID
      4253
      时间
      1000ms
      内存
      128MiB
      难度
      8
      标签
      递交数
      23
      已通过
      4
      上传者