zoukankan      html  css  js  c++  java
  • [TS-A1505] [清橙2013中国国家集训队第二次作业] 树 [可持久化线段树,求树上路径第k大]

    按Dfs序逐个插入点,建立可持久化线段树,每次查询即可,具体详见代码。

    不知道为什么,代码慢的要死,,

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <ctime>
    #include <vector>
    
    using namespace std;
    
    template<const int _n,const int _m>
    struct Edge
    {
        struct Edge_base { int    to,next; }e[_m];
        int    cnt,p[_n];
        Edge() { clear(); }
        void    insert(const int x,const int y)
        { e[++cnt].to=y; e[cnt].next=p[x]; p[x]=cnt; return ; }
        int    start(const int x) { return p[x]; }
        void    clear() { cnt=1,memset(p,0,sizeof(p)); }
        Edge_base&    operator[](const int x) { return e[x]; }
    };
    
    Edge<110000,210000>    e;
    vector<int>    vec;
    int    n,q,tot,cnt;
    int    a[110000],root[110000],Left[3100000],Right[3100000];
    int    val[3100000],f[110000][19],depth[110000],lg2[110000];
    
    void    Init()
    {
        for(int j=1;(1<<j)<=n;++j)
            for(int i=1;i<=n;++i)
                f[i][j]=f[f[i][j-1]][j-1];
        for(int i=2;i<=n;++i)lg2[i]=lg2[i>>1]+1;
        return ;
    }
    
    int    Lca(int A,int B)
    {
        int    i,j;
        if(depth[A]<depth[B])swap(A,B);
    
        j=lg2[depth[A]];
    
        for(i=j;i>=0;--i)
        {
            if(depth[A]-(1<<i)>=depth[B])A=f[A][i];
        }
    
        if(A==B)return A;
    
        for(i=j;i>=0;--i)
        {
            if(f[A][i] && f[A][i]!=f[B][i])
                A=f[A][i],B=f[B][i];
        }
        return f[A][0];
    }
    
    void    Insert(const int l,const int r,const int root_l,int& root_r,const int d)
    {
        val[root_r=++tot]=val[root_l]+1;
        if(l==r)return ;
    
        int mid=l+((r-l)>>1);
        if(d<=mid)
        {
            Right[root_r]=Right[root_l];
            Insert(l,mid,Left[root_l],Left[root_r],d);
        }
        else
        {
            Left[root_r]=Left[root_l];
            Insert(mid+1,r,Right[root_l],Right[root_r],d);
        }
    
        return ;
    }
    
    void    Dfs(const int S,const int fa)
    {
        depth[S]=depth[fa]+1;
        f[S][0]=fa;
    
        a[S]=lower_bound(vec.begin(),vec.end(),a[S])-vec.begin()+1;
        Insert(1,vec.size(),root[fa],root[S],a[S]);
    
        for(int i=e.start(S);i;i=e[i].next)
        {
            if(e[i].to==fa)continue;
            Dfs(e[i].to,S);
        }
    }    
    
    int    kth(int l,int r,int r1,int r2,int r3,int r4,int d)
    {
        while(true)
        {
            if(l==r)return l;
            int    mid=l+((r-l)>>1),temp;
            temp=val[Left[r1]]+val[Left[r2]]-val[Left[r3]]-val[Left[r4]];
            if(temp>=d)r=mid,r1=Left[r1],r2=Left[r2],r3=Left[r3],r4=Left[r4];
            else    l=mid+1,r1=Right[r1],r2=Right[r2],r3=Right[r3],r4=Right[r4],d=d-temp;
        }
        return 0;
    }
    
    int main()
    {
        //freopen("in","r",stdin);
    
        int    i,x,y,op;
    
        vec.resize(110000);
        scanf("%d%d",&n,&q);
    
        for(i=1;i<=n;++i)
            scanf("%d",&a[i]),vec.push_back(a[i]);
    
        sort(vec.begin(),vec.end());
        vec.erase(unique(vec.begin(),vec.end()),vec.end());
    
        for(i=1;i<n;++i)
        {
            scanf("%d%d",&x,&y);
            e.insert(x,y);
            e.insert(y,x);
        }
    
        Dfs(1,0);
        Init();
    
        for(i=1;i<=q;++i)
        {
            scanf("%d%d%d",&op,&x,&y);
            int    temp=Lca(x,y),temp1;
            if(op==1)
                temp1=kth(1,vec.size(),
                        root[x],root[y],
                        root[temp],root[f[temp][0]],1);
            else if(op==2)
                temp1=kth(1,vec.size(),
                        root[x],root[y],
                        root[temp],root[f[temp][0]],
                        depth[x]+depth[y]-(depth[temp]<<1)+1);
            else    temp1=kth(1,vec.size(),
                    root[x],root[y],
                    root[temp],root[f[temp][0]],
                    ((depth[x]+depth[y]-(depth[temp]<<1)+1)>>1)+1);
    
            printf("%d
    ",vec[temp1-1]);
        }
    
        return 0;
    }
  • 相关阅读:
    pig 调试(explain&amp;illerstrate)
    ufldl学习笔记与编程作业:Linear Regression(线性回归)
    EasyUI基础入门之Pagination(分页)
    codevs1052
    1040. Longest Symmetric String (25)
    Appium
    lua实现大数运算
    创建一个Spring的HelloWorld程序
    [Swift]LeetCode495. 提莫攻击 | Teemo Attacking
    [Swift]LeetCode992. K 个不同整数的子数组 | Subarrays with K Different Integers
  • 原文地址:https://www.cnblogs.com/Gster/p/4996922.html
Copyright © 2011-2022 走看看