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;
    }
  • 相关阅读:
    arcgis api 3.x for js 入门开发系列八聚合效果(附源码下载)
    arcgis api 3.x for js 入门开发系列七图层控制(附源码下载)
    arcgis api 3.x for js 入门开发系列六地图分屏对比(附源码下载)
    arcgis api 3.x for js 入门开发系列五地图态势标绘(附源码下载)
    arcgis api 3.x for js 入门开发系列四地图查询(附源码下载)
    Java里面获取当前服务器的IP地址
    Flutter at Google I/O 2018
    Modbus RTU 协议使用汇总
    plsql 创建表空间、用户、赋予权限
    Oracle:ODP.NET Managed 小试牛刀
  • 原文地址:https://www.cnblogs.com/Mrleon/p/9097900.html
Copyright © 2011-2022 走看看