zoukankan      html  css  js  c++  java
  • RMQ 与 LCA-ST算法

    RMQ算法

    区间求最值的算法,用区间动态规划(nlogn)预处理,查询O(1)

    http://blog.csdn.net/y990041769/article/details/38405063

    (POJ 3264)

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<string>
    #include<sstream>
    #define eps 1e-9
    #define ALL(x) x.begin(),x.end()
    #define INS(x) inserter(x,x.begin())
    #define rep(i,j,k) for(int i=j;i<=k;i++)
    #define MAXN 1005
    #define MAXM 40005
    #define INF 0x3fffffff
    #define PB push_back
    #define MP make_pair
    #define X first
    #define Y second
    #define clr(x,y) memset(x,y,sizeof(x));
    using namespace std;
    typedef long long LL;
    int i,j,k,n,m,x,y,T,ans,big,cas,num,len;
    bool flag;
    int a[50005],mm[50005][30],mi[50005][30];
    
    void rmq()
    {
        for (int i=1;i<=n;i++)
        {
            mm[i][0]=mi[i][0]=a[i];
        }
        for (int j=1;(1<<j)<=n;j++)
        {
            for (int i=1;i+(1<<j)-1<=n;i++)
            {
                mm[i][j]=max(mm[i][j-1],mm[i+(1<<(j-1))][j-1]);
                mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
            }
        }
    }
    
    int getans(int l,int r)
    {
        int k=0;
        while ((1<<(k+1))<=r-l+1) k++;
        int ans1=max(mm[l][k],mm[r-(1<<k)+1][k]);
        int ans2=min(mi[l][k],mi[r-(1<<k)+1][k]);
        return ans1-ans2;
    }
    
    int main()
    {
        while (~scanf("%d%d",&n,&m))
        {
            clr(mm,0);clr(mi,0);
            for (i=1;i<=n;i++) scanf("%d",&a[i]);
            rmq();
            for (i=1;i<=m;i++)
            {
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%d
    ",getans(l,r));
            }
        }
    
        return 0;
    }

    大概看了看求LCA的ST算法,其思路很简单,就是树形转线性,

    如果求a与b的最近公共祖先,就是确定first[a]~first[b]中深度最小的点,即求区间最小值,用RMQ维护即可。

    http://blog.csdn.net/y990041769/article/details/40887469

    hdu2586

    #pragma comment(linker, "/STACK:1024000000,1024000000") 
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<string>
    #include<sstream>
    #define eps 1e-9
    #define ALL(x) x.begin(),x.end()
    #define INS(x) inserter(x,x.begin())
    #define rep(i,j,k) for(int i=j;i<=k;i++)
    #define MAXN 80005
    #define MAXM 80005
    #define INF 0x3fffffff
    #define PB push_back
    #define MP make_pair
    #define X first
    #define Y second
    #define clr(x,y) memset(x,y,sizeof(x));
    using namespace std;
    typedef long long LL;
    int i,j,k,n,m,x,y,T,ans,big,cas,num,len;
    bool flag;
    
    int edge,head[MAXN],id[MAXN],dir[MAXN],first[MAXN],R[MAXN],vis[MAXN],tot;
    int dp[MAXN][25];
    struct edgenode
    {
        int to,next,w;
    } G[MAXM];
    
    void add_edge(int x,int y,int w)
    {
        G[edge].to=y;
        G[edge].w=w;
        G[edge].next=head[x];
        head[x]=edge++;
    }
    
    void dfs(int u,int dep)
    {
        vis[u]=true;id[++tot]=u;
        first[u]=tot;R[tot]=dep;
        for (int i=head[u];i!=-1;i=G[i].next)
        {
            int v=G[i].to;
            if (!vis[v])
            {
                int w=G[i].w;
                dir[v]=dir[u]+w;
                dfs(v,dep+1);
                id[++tot]=u; R[tot]=dep;
            }
        }
    }
    
    void ST(int n)
    {
        for (int i=1;i<=n;i++)
        {
            dp[i][0]=i;
        }
        for (int j=1;(1<<j)<=n;j++)
        {
            for (int i=1;i+(1<<j)-1<=n;i++)
            {
                int a=dp[i][j-1],b=dp[i+(1<<(j-1))][j-1];
                if (R[a]<R[b]) dp[i][j]=a; else dp[i][j]=b;
            }
        }
    }
    
    int RMQ(int l,int r)
    {
        int k=0;
        while ((1<<(k+1))<=r-l+1) k++;
        int a=dp[l][k],b=dp[r-(1<<k)+1][k];
        return R[a]<R[b]?a:b;
    }
    
    int LCA(int u,int v)
    {
        int x=first[u],y=first[v];
        if (x>y) swap(x,y);
        return id[RMQ(x,y)];
    }
    
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            memset(head,-1,sizeof(head));
            edge=0;tot=0;
            scanf("%d%d",&n,&m);
            for (i=1;i<n;i++)
            {
                int x,y,d;
                scanf("%d%d%d",&x,&y,&d);
                add_edge(x,y,d);
                add_edge(y,x,d);
            }
            memset(vis,0,sizeof(vis));
            dfs(1,1);
            ST(2*n-1);
            for (i=1;i<=m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                int lca=LCA(u,v);
                printf("%d
    ",dir[u]+dir[v]-2*dir[lca]);
            }
        }
        return 0;
    }
  • 相关阅读:
    天气预报APP(2)
    天气预报APP(1)
    android ——网络编程
    android ——Intent
    android ——可折叠式标题栏
    5.1 类,实例,实现,方法
    5.0 面向对象
    python 基础
    模拟实现一个ATM + 购物商城程序
    python 基础
  • 原文地址:https://www.cnblogs.com/zhyfzy/p/4696766.html
Copyright © 2011-2022 走看看