• HDU 4123(两种方法-RMQ,单调队列)


    题意:50000个点的树,每个点有一个人,每个人会跑到离自己初始点距离最远的点上,这个距离为distance[i]。给你500个查询,对于每个查询Q,找一段连续编号的人,比如[left,right],满足 max( distance[i]  i∈[left,right] ) – min( distance[i]  i∈[left,right] ) ≤ Q,并且使得length=right-left+1要最大,求这个最大的length

    法一:关键是O(1)的RMQ。。。。

    分析:求distance[i]数组(代码中的d),可以用搜边的方法来解决,然后线性维护一个队列,使得队列中的最大值 – 最小值 ≤ Q,之后,会有一个新的distance[i]插到队列的头部,这样会打破“最大值 – 最小值 ≤ Q”的规则,此时要从队列末尾弹出元素,直到重新满足规则。很明显,维护队列的时候要不断查询某一区间的最大值和最小值,这个可以用RMQ来解决。对于每个distance[i],最多进队列和出队列一次,所以总复杂度为O(nlogn+mn),这貌似有点大啊。

    此题还必须有一个极端的优化(当时赛后才想到这个,悲剧。):由于维护队列的时候要不断查询某一区间的最大值和最小值,而log函数慢的一比,所以,要预处理log数组

    #include<cstdlib>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<list>
    #include<queue>
    #include<stack>
    #include<vector>
    #define tree int o,int l,int r
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define lo o<<1
    #define ro o<<1|1
    #define pb push_back
    #define mp make_pair
    #define ULL unsigned long long
    #define LL long long
    #define inf 0x7fffffff
    #define eps 1e-7
    #define N 50009
    using namespace std;
    int m,n,T,t,x,y,z;
    vector<pair<int,int> >g[N];
    int f[N],s[N],sub[N];
    int minv[N][17],maxv[N][17];
    int lg[N];
    void init()
    {
        for (int i=0; i<=n; ++i )
            g[i].clear();
    }
    void dfs1(int u,int fa)
    {
        f[u]=s[u]=0;
        for(int i=0; i<g[u].size(); i++)
        {
            int v=g[u][i].first;
            int l=g[u][i].second;
            if(v!=fa)
            {
                dfs1(v,u);
                if(f[u]<f[v]+l)
                {
                    s[u]=f[v]+l;
                    swap(s[u],f[u]);
                    sub[u]=v;
                }
                else if(s[u]<f[v]+l)
                {
                    s[u]=f[v]+l;
                }
            }
        }
    }
    void dfs2(int u,int fa)
    {
        for(int i=0; i<g[u].size(); i++)
        {
            int v=g[u][i].first;
            int l=g[u][i].second;
            if(v!=fa)
            {
                int val;
                if(sub[u]==v)
                    val=s[u];
                else
                    val=f[u];
                val+=l;
                if(f[v]<val)
                {
                    s[v]=val;
                    swap(s[v],f[v]);
                    sub[v]=u;
                }
                else if(s[v]<val)
                {
                    s[v]=val;
                }
                dfs2(v,u);
            }
        }
    }
    void rmqinit()
    {
        for(int i=1; i<=n; i++)
            minv[i][0]=maxv[i][0]=f[i];
        for(int j=1; (1<<j)<=n; j++)
            for(int i=1; i+(1<<j)-1<=n; i++)
            {
                minv[i][j]=min(minv[i][j-1],minv[i+(1<<(j-1))][j-1]);
                maxv[i][j]=max(maxv[i][j-1],maxv[i+(1<<(j-1))][j-1]);
            }
    }
    int rmqx(int l,int r)
    {
        int len=lg[r-l+1];
        return min(minv[l][len],minv[r-(1<<len)+1][len]);
    }
    int rmqd(int l,int r)
    {
        int len=lg[r-l+1];
        return max(maxv[l][len],maxv[r-(1<<len)+1][len]);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("ex.in","r",stdin);
    #endif
        for(int i=1,j=0; i<N; i++)//预处理使RMQ的复杂度变为O(1)
        {
            if(i<=(1<<(j+1)))
                lg[i]=j;
            else
                lg[i]=++j;
        }
        while(scanf("%d%d%*c",&n,&m)==2)
        {
            if(!n&&!m)return 0;
            init();
            for (int i=0; i<n-1; ++i )
            {
                scanf("%d%d%d",&x,&y,&z);
                g[x].pb(mp(y,z));
                g[y].pb(mp(x,z));
            }
            dfs1(1,-1);
            dfs2(1,-1);
            rmqinit();//O(nlgn)
            while(m--)//O(mn)
            {
                int q,ans=1;
                scanf("%d",&q);
                int d=0,x=inf,j=1;
                for(int i=1; i<=n; i++)
                {
                    d=max(d,f[i]);
                    x=min(x,f[i]);
                    if(d-x>q)
                    {
                        j++;
                        int xiao=rmqx(j,i);//O(1)
                        int da=rmqd(j,i);
                        while(da-xiao>q)//j==i时会停
                        {
                            j++;
                            xiao=rmqx(j,i);
                            da=rmqd(j,i);
                        }
                        d=da;///////////
                        x=xiao;
                    }
                    ans=max(ans,i-j+1);
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    View Code

    法二:两个单调队列(一个维护最大,一个维护最小)

    #include<cstdlib>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<list>
    #include<queue>
    #include<stack>
    #include<vector>
    #define tree int o,int l,int r
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define lo o<<1
    #define ro o<<1|1
    #define pb push_back
    #define mp make_pair
    #define ULL unsigned long long
    #define LL long long
    #define inf 0x7fffffff
    #define eps 1e-7
    #define N 50009
    using namespace std;
    int m,n,T,t,x,y,z;
    vector<pair<int,int> >g[N];
    int f[N],s[N],sub[N];
    int qs[N],qj[N];
    void init()
    {
        for (int i=0; i<=n; ++i )
            g[i].clear();
    }
    void dfs1(int u,int fa)
    {
        f[u]=s[u]=0;
        for(int i=0; i<g[u].size(); i++)
        {
            int v=g[u][i].first;
            int l=g[u][i].second;
            if(v!=fa)
            {
                dfs1(v,u);
                if(f[u]<f[v]+l)
                {
                    s[u]=f[v]+l;
                    swap(s[u],f[u]);
                    sub[u]=v;
                }
                else if(s[u]<f[v]+l)
                {
                    s[u]=f[v]+l;
                }
            }
        }
    }
    void dfs2(int u,int fa)
    {
        for(int i=0; i<g[u].size(); i++)
        {
            int v=g[u][i].first;
            int l=g[u][i].second;
            if(v!=fa)
            {
                int val;
                if(sub[u]==v)
                    val=s[u];
                else
                    val=f[u];
                val+=l;
                if(f[v]<val)
                {
                    s[v]=val;
                    swap(s[v],f[v]);
                    sub[v]=u;
                }
                else if(s[v]<val)
                {
                    s[v]=val;
                }
                dfs2(v,u);
            }
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("ex.in","r",stdin);
    #endif
        while(scanf("%d%d%*c",&n,&m)==2)
        {
            if(!n&&!m)return 0;
            init();
            for (int i=0; i<n-1; ++i )
            {
                scanf("%d%d%d",&x,&y,&z);
                g[x].pb(mp(y,z));
                g[y].pb(mp(x,z));
            }
            dfs1(1,-1);
            dfs2(1,-1);
            while(m--)//O(mn)
            {
                int q,ans=1;
                scanf("%d",&q);
                int sl=0,sr=0,jl=0,jr=0,temp=0;
                for(int i=1; i<=n; i++)
                {
                    while(sl<sr&&f[qs[sr-1]]>=f[i])sr--;
                    while(jl<jr&&f[qj[jr-1]]<=f[i])jr--;
                    qs[sr++]=i;
                    qj[jr++]=i;
                    while(f[qj[jl]]-f[qs[sl]]>q)//对于右区间i,找到左区间!
                    {
                        if(qj[jl]<qs[sl])
                            temp=max(temp,qj[jl++]);
                        else
                            temp=max(temp,qs[sl++]);
                    }
                    ans=max(ans,i-temp);
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Microsoft Dynamics CRM2011 更换Logo
    Calling LoadLibraryEx on ISAPI filter failed
    Dynamics CRM2013/2015 插件注册工具登录后无法显示assembly列表问题的解决办法二
    python字符串
    python流程控制
    python反射
    python内置函数
    python集合
    python字符编码
    测试appstore地址
  • 原文地址:https://www.cnblogs.com/sbaof/p/3384782.html
Copyright © 2020-2023  润新知