zoukankan      html  css  js  c++  java
  • 洛谷 P2633 Count on a tree

    ->题目链接

    题解:

    主席树,可持久化,最近公共祖先,LCA,线段树

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100001 
    using namespace std;
    int n,m,tot,cnt,num,lastans;
    int a[MAXN],ha[MAXN],root[MAXN],to[MAXN*2],net[MAXN*2],head[MAXN*2],top[MAXN],dad[MAXN],deep[MAXN],size[MAXN];
    struct node{
        int l,r,cnt;
    }tree[MAXN*20];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
        to[++tot]=u;net[tot]=head[v];head[v]=tot;
    }
    void insert(int pre,int &now,int l,int r,int k){
        tree[now=++num].cnt=tree[pre].cnt+1;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(k<=mid){
            tree[now].r=tree[pre].r;
            insert(tree[pre].l,tree[now].l,l,mid,k);
        }
        else{
            tree[now].l=tree[pre].l;
            insert(tree[pre].r,tree[now].r,mid+1,r,k);
        }
    }
    int query(int x,int y,int LCA,int fa_LCA,int l,int r,int k){
        if(l==r) return a[l];
        int mid=(l+r)>>1;
        int tmp=tree[tree[x].l].cnt+tree[tree[y].l].cnt-tree[tree[LCA].l].cnt-tree[tree[fa_LCA].l].cnt;
        if(k<=tmp) query(tree[x].l,tree[y].l,tree[LCA].l,tree[fa_LCA].l,l,mid,k);
        else query(tree[x].r,tree[y].r,tree[LCA].r,tree[fa_LCA].r,mid+1,r,k-tmp);
    }
    void dfs(int now){
        size[now]=1;
        insert(root[dad[now]],root[now],1,cnt,ha[now]);
        deep[now]=deep[dad[now]]+1;
        for(int i=head[now];i;i=net[i])
            if(dad[now]!=to[i]){
                dad[to[i]]=now;
                dfs(to[i]);
                size[now]+=size[to[i]];
            } 
    }
    void dfs1(int x){
        int t=0;
        if(top[x]==0) top[x]=x;
        for(int i=head[x];i;i=net[i])
            if(dad[x]!=to[i]&&size[to[i]]>size[t]) t=to[i];
        if(t){
            top[t]=top[x];dfs1(t);
        }
        for(int i=head[x];i;i=net[i])
            if(dad[x]!=to[i]&&t!=to[i]) dfs1(to[i]);
    }
    int lca(int x,int y){
        for(;top[x]!=top[y];){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            x=dad[top[x]];
        }
        if(deep[x]>deep[y]) swap(x,y);
        return x;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),ha[i]=a[i];
        for(int i=1,u,v;i<n;i++)
            scanf("%d%d",&u,&v),add(u,v);
        sort(a+1,a+n+1);
        cnt=unique(a+1,a+1+n)-a-1;
        for(int i=1;i<=n;i++)
            ha[i]=lower_bound(a+1,a+1+cnt,ha[i])-a;
        dfs(1);
        dfs1(1);
        for(int i=1,u,k,v;i<=m;i++){
            scanf("%d%d%d",&u,&v,&k);
            u^=lastans;
            int LCA=lca(u,v);
            lastans=query(root[u],root[v],root[LCA],root[dad[LCA]],1,cnt,k);
            if(i!=m) cout<<lastans<<"
    ";
            else cout<<lastans;
        }
        return 0;
    }
    AC

    给你个可以令你终生受益的建议。

    啊?

    和我在一起。

  • 相关阅读:
    5.19 省选模拟赛 T1 小B的棋盘 双指针 性质
    5.15 省选模拟赛 容斥 生成函数 dp
    5.15 省选模拟赛 T1 点分治 FFT
    5.15 牛客挑战赛40 B 小V的序列 关于随机均摊分析 二进制
    luogu P4929 【模板】舞蹈链 DLX
    CF 878E Numbers on the blackboard 并查集 离线 贪心
    5.10 省选模拟赛 拍卖 博弈 dp
    5.12 省选模拟赛 T2 贪心 dp 搜索 差分
    5.10 省选模拟赛 tree 树形dp 逆元
    luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树
  • 原文地址:https://www.cnblogs.com/GTBD/p/9435808.html
Copyright © 2011-2022 走看看