zoukankan      html  css  js  c++  java
  • HDU 5266 pog loves szh III (线段树+在线LCA转RMQ)

    题目地址:HDU 5266
    这题用转RMQ求LCA的方法来做的很easy,仅仅须要找到l-r区间内的dfs序最大的和最小的就能够。那么用线段树或者RMQ维护一下区间最值就能够了。然后就是找dfs序最大的点和dfs序最小的点的近期公共祖先了。


    代码例如以下:

    #include <iostream>
    #include <string.h>
    #include <math.h>
    #include <queue>
    #include <algorithm>
    #include <stdlib.h>
    #include <map>
    #include <set>
    #include <stdio.h>
    using namespace std;
    #define LL __int64
    #define pi acos(-1.0)
    #define root 1, n, 1
    #define lson l, mid, rt<<1
    #define rson mid+1, r, rt<<1|1
    #pragma comment(linker, "/STACK:1024000000")
    const int mod=1e4+7;
    const int INF=0x3f3f3f3f;
    const double eqs=1e-9;
    const int MAXN=300000+10;
    int fir[MAXN], F[MAXN<<1], tot, deg[MAXN], rmq[MAXN<<1];
    int head[MAXN], cnt, n;
    int dp[MAXN<<1][30];
    int Max[MAXN<<2], Min[MAXN<<2], q_max, q_min;
    struct node
    {
            int u, v, next;
    }edge[MAXN<<1];
    void add(int u, int v)
    {
            edge[cnt].v=v;
            edge[cnt].next=head[u];
            head[u]=cnt++;
    }
    void init()
    {
            memset(head,-1,sizeof(head));
            cnt=tot=0;
    }
    void dfs(int u, int dep, int fa)
    {
            F[++tot]=u;
            rmq[tot]=dep;
            fir[u]=tot;
            for(int i=head[u];i!=-1;i=edge[i].next){
                    int v=edge[i].v;
                    if(v==fa) continue ;
                    dfs(v,dep+1,u);
                    F[++tot]=u;
                    rmq[tot]=dep;
            }
    }
    struct ST
    {
            int i, j;
            void init()
            {
                    for(i=1;i<=tot;i++) dp[i][0]=i;
                    for(j=1;(1<<j)<=tot;j++){
                            for(i=1;i<=tot-(1<<j)+1;i++){
                                    dp[i][j]=rmq[dp[i][j-1]]<rmq[dp[i+(1<<j-1)][j-1]]?dp[i][j-1]:dp[i+(1<<j-1)][j-1];
                            }
                    }
            }
            int Query(int l, int r)
            {
                    if(r<l) swap(l,r);
                    int k=0;
                    while((1<<k+1)<=r-l+1) k++;
                    return rmq[dp[l][k]]<rmq[dp[r+1-(1<<k)][k]]?

    dp[l][k]:dp[r+1-(1<<k)][k]; } }st; void PushUp(int rt) { Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); Min[rt]=min(Min[rt<<1],Min[rt<<1|1]); } void Build(int l, int r, int rt) { if(l==r){ Max[rt]=Min[rt]=fir[l]; return ; } int mid=l+r>>1; Build(lson); Build(rson); PushUp(rt); } void Query(int ll, int rr, int l, int r, int rt) { if(ll<=l&&rr>=r){ q_max=max(q_max,Max[rt]); q_min=min(q_min,Min[rt]); return ; } int mid=l+r>>1; if(ll<=mid) Query(ll,rr,lson); if(rr>mid) Query(ll,rr,rson); } int main() { int q, u, v, l, r, i; while(scanf("%d",&n)!=EOF){ init(); for(i=1;i<n;i++){ scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs(1,0,-1); st.init(); Build(root); scanf("%d",&q); while(q--){ scanf("%d%d",&u,&v); if(u>v) swap(u,v); q_min=INF; q_max=0; Query(u,v,root); //printf("%d %d ",q_min,q_max); printf("%d ",F[st.Query(q_min,q_max)]); } } return 0; }

  • 相关阅读:
    CentOS安装sctp协议
    视频编码未来简史
    Linux内核:分析coredump文件
    skb的两个函数pskb_copy和skb_copy
    《Linux内核设计与实现》读书笔记(十二)- 内存管理
    Linux内核学习笔记之seq_file接口创建可读写proc文件
    内核如何签名
    《女士品茶》与统计检验
    K近邻算法
    PCA原理分析
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5263633.html
Copyright © 2011-2022 走看看