• P2633 Count on a tree


    P2633 Count on a tree

    静态第 (k) 小,想到主席树。

    但是主席树大多数情况下是序列问题,这道题在树上。

    想一想之前写过的第 (k) 小板子,发现主席树是具有前缀性质的。

    于是在这道题中,考虑将原本主席树中:(i) 棵线段树维护前 (i) 个数的出现次数 改为 (i) 棵线段树表示结点 (i) 到根的路径中数的出现次数

    然后根据这个维护前缀的定义,取出 (u->v) 路径上这一段数时,将路径分为 (3) 部分

    1. (u->LCA)下面一层,这就是 (sum(u)-sum(LCA))
    2. (v-> LCA)下面一层,就是 (sum(v)-sum(LCA))
    3. (LCA)(sum(LCA)-sum(fa_{LCA}))

    将这些加起来就是这条路径上对应主席树的位置。

    即将查询时将原本的

    sum(ls(u))-sum(ls(v))
    

    改为:

    sum(ls(u))+sum(ls(v))-sum(ls(lca))-sum(ls(falca))
    

    就可以了。

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
        x=0;char ch=getchar();bool f=false;
        while(!isdigit(ch)) f|=ch=='-',ch=getchar();
        while(isdigit(ch))  x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;return;
    }
    template <typename T>
    inline void print(T x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) print(x/10);
        putchar(x%10^48);return;
    }
    const int N=1e5+3,M=1e5+3;
    struct Seg_Tree{
        int ls,rs,sum;
        #define ls(x)   c[x].ls
        #define rs(x)   c[x].rs
        #define sum(x)  c[x].sum
    }c[N*32];
    int rt[N],cnt,head[N],to[N<<1],Next[N<<1],tot,n,m,len;
    int a[N],b[N],siz[N],son[N],fa[N],top[N],dep[N];
    //Graph
    inline void Add_edge(int u,int v){Next[++tot]=head[u],head[u]=tot,to[tot]=v;return;}
    //Seg_Tree
    inline void Push_up(int x){sum(x)=sum(ls(x))+sum(rs(x));return;}
    
    inline void Build(int &x,int l,int r){
        x=++cnt;
        if(l==r)    return;
        int mid=(l+r)>>1;
        Build(ls(x),l,mid),Build(rs(x),mid+1,r);
    }
    
    inline void Insert(int &x,int pre,int l,int r,int q){
        x=++cnt;c[x]=c[pre];
        if(l==r){sum(x)+=1;return;}
        int mid=(l+r)>>1;
        if(mid>=q)  Insert(ls(x),ls(pre),l,mid,q);
        else Insert(rs(x),rs(pre),mid+1,r,q);
        Push_up(x);return;
    }
    
    inline int Query(int u,int v,int lca,int falca,int l,int r,int k){
        if(l==r)    return b[l];
        int mid=(l+r)>>1,tep=sum(ls(u))+sum(ls(v))-sum(ls(lca))-sum(ls(falca));
        if(tep>=k)  return Query(ls(u),ls(v),ls(lca),ls(falca),l,mid,k);
        else return Query(rs(u),rs(v),rs(lca),rs(falca),mid+1,r,k-tep);
    }
    
    //Tree Chain Partition
    inline void Dfs1(int x,int f){
        fa[x]=f,siz[x]=1,dep[x]=dep[f]+1;
        for(register int i=head[x];i;i=Next[i]){
            int y=to[i];
            if(y==f)   continue;
            Dfs1(y,x);siz[x]+=siz[y];
            if(siz[y]>siz[son[x]])  son[x]=y;
        }
        return;
    }
    
    inline void Dfs2(int x){
        Insert(rt[x],rt[fa[x]],1,len,a[x]);
        top[x]=(son[fa[x]]==x ? top[fa[x]] : x);
        if(son[x])  Dfs2(son[x]);
        for(register int i=head[x];i;i=Next[i]){
            int y=to[i];
            if(y==fa[x]||y==son[x]) continue;
            Dfs2(y);
        }
        return;
    }
    
    inline int LCA(int u,int v){
    	while(top[u]!=top[v]){
    		if(dep[top[u]]>dep[top[v]])	u=fa[top[u]];
    		else v=fa[top[v]];
    	}
    	return dep[u] > dep[v] ? v : u;
    }
    
    int main(){
        // system("fc my.out P2633_1.out");
        // freopen("P2633_1.in","r",stdin);
        // freopen("my.out","w",stdout);
        read(n),read(m);
        for(register int i=1;i<=n;++i)  read(a[i]),b[i]=a[i];
        sort(b+1,b+n+1);len=unique(b+1,b+n+1)-(b+1);
        for(register int i=1;i<=n;++i)  a[i]=lower_bound(b+1,b+len+1,a[i])-b;
        Build(rt[0],1,len);
        for(register int i=1;i<n;++i){
            int u,v;read(u),read(v);
            Add_edge(u,v),Add_edge(v,u);
        }
        Dfs1(1,0);Dfs2(1);int last=0;
        while(m--){
            int u,v,k;
            read(u),read(v),read(k);u^=last;
            assert(u<=n);
            int lca=LCA(u,v);
            last=Query(rt[u],rt[v],rt[lca],rt[fa[lca]],1,len,k);
            print(last),putchar('
    ');
        }
        return 0;
    }
    
    
  • 相关阅读:
    js 遇到问题
    table 排序 添加 删除 等操作
    json对象
    .style, .getComputedStyle(),.currentStyle区别
    3个div 宽度移入移出时变化
    运动 js
    OWASP Top 10之文件上传漏洞简析(二)
    owasp top10 之文件上传漏洞简析
    前台实现ajax 需注意的地方
    apache-Rewrite重写规则配置
  • 原文地址:https://www.cnblogs.com/NuoCarter/p/14682013.html
Copyright © 2020-2023  润新知