zoukankan      html  css  js  c++  java
  • SPOJ Count on a tree 主席树+lca

    传送门

    题意:给你一棵树,询问u到v路径上的第k大

    题解:从u到v的路径能想到,u到根+v到根-lca(u,v)到根-fa[lca(u,v)]到根剩下的就是u到v之间的路径。因此只要离散化一下,每次dfs的时候处理倍增lca和主席树更新操作就可以

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <map>
    #include <queue>
    #include <vector>
    #include <cstring>
    #include <iomanip>
    #include <set>
    #include<ctime>
    //CLOCKS_PER_SEC
    #define se second
    #define fi first
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define Pii pair<int,int>
    #define Pli pair<ll,int>
    #define ull unsigned long long
    #define pb push_back
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    const double Pi=3.14159265;
    const int N=1e5+10;
    const ull base=163;
    const int INF=0x3f3f3f3f;
    using namespace std;
    int n,m, root[N], a[N],cnt=0;
    struct node {
        int l,r,sum;
    }T[40*N];
    int New[N];
    int fa[N][20];
    int dep[N];
    vector<int>v;
    int head[N],to[2*N],nx[2*N],tot=1;
    void add(int u,int v){
        to[tot]=v;
        nx[tot]=head[u];
        head[u]=tot++;
    }
    int getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
    void update(int l,int r,int &x,int y,int pos){
        T[++cnt]=T[y],T[cnt].sum++,x=cnt;
        if(l==r)return ;
        int m=(l+r)>>1;
        if(pos<=m)update(l,m,T[x].l,T[y].l,pos);
        else update(m+1,r,T[x].r,T[y].r,pos);
    }
    void dfs(int u,int  pre){
        fa[u][0]=pre;
        dep[u]=dep[pre]+1;
        update(1,n,root[u],root[pre],New[u]);
        for(int i=1;i<17;i++){
            fa[u][i]=fa[fa[u][i-1]][i-1];
        }
        for(int i=head[u];i;i=nx[i]){
            int v=to[i];
            if(pre==v)continue;
            dfs(v,u);
        }
    }
    int LCA(int u,int v){
        if(dep[u]<dep[v])swap(u,v);
        int d=dep[u]-dep[v];
        for(int i=0;(1<<i)<=d;i++){
            if((1<<i)&d)u=fa[u][i];
        }
        if(u==v)return u;
        for(int i=16;i>=0;i--){
            if(fa[v][i]!=fa[u][i]){
                u=fa[u][i];
                v=fa[v][i];
            }
        }
        return fa[u][0];
    }
    int query(int l,int r,int k,int x,int y,int z,int w){
        if(l==r)return l;
        int m=(l+r)>>1;
        int d=T[T[x].l].sum+T[T[y].l].sum-T[T[z].l].sum-T[T[w].l].sum;
        if(d>=k)return query(l,m,k,T[x].l,T[y].l,T[z].l,T[w].l);
        else return query(m+1,r,k-d,T[x].r,T[y].r,T[z].r,T[w].r);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),v.pb(a[i]);
        sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());
        for(int i=1;i<=n;i++)New[i]=getid(a[i]);
        for(int i=1;i<=n-1;i++){
            int u,v;scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs(1,0);
        for(int i=1;i<=m;i++){
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            printf("%d
    ",v[query(1,n,k,root[l],root[r],root[LCA(l,r)],root[fa[LCA(l,r)][0]])-1]);
        }
        return 0;
    }
  • 相关阅读:
    设计模式之桥接模式
    设计模式之观察者模式
    设计模式之装饰者模式
    设计模式之适配器模式
    2 深入分析 Java IO的工作机制(二)
    struts2常用标签使用说明
    JDK环境变量配置
    Oracle恢复删除数据 && connect by 树形结构查询
    Spring和Hibernate集成配置
    Struts2中重定向和请求转发配置
  • 原文地址:https://www.cnblogs.com/Mrleon/p/9097900.html
Copyright © 2011-2022 走看看