zoukankan      html  css  js  c++  java
  • hdu3607 Traversal (dp+离散+线段树)

    很明显的状态转移方程式:dp[i]=max(dp[j])+g[i], (0<=j<i && h[i]>h[j])

    不过注意到题目中n的范围有10000 ,n^2的算法…………

    我们可以用线段树优化一下

    先对高度离散化,作为线段树左右区间的端点

    这样,求dp[i]时,只需要查出高度(0,h[i]-1]范围内的最大值t,那么dp[i]=t+g[i], 之后,接着,更新线段树中高度为g[i],值为dp[i]的点

    View Code
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<map>
    using namespace std;
    const int N = 100000+10;
    struct node
    {
        int l,r,maxx;
    }p[N*3];
    int n,dp[N],g[N],h[N];
    map<int,int> ms; 
    void bulid(int s,int t,int k)
    {
        p[k].l=s,p[k].r=t;
        p[k].maxx=0;
        if(s==t)
            return ;
        int kl=k<<1,kr=kl+1,mid=(s+t)>>1;
        bulid(s,mid,kl);
        bulid(mid+1,t,kr);
    }
    void update(int k,int tt,int key)
    {
        if(p[k].l==tt && p[k].r==tt)
        {
            p[k].maxx=max(key,p[k].maxx);
            return ;
        }
        int kl=k<<1,kr=kl+1,mid=(p[k].l+p[k].r)>>1;
        if(tt<=mid)
            update(kl,tt,key);
        else update(kr,tt,key);
        p[k].maxx=max(p[kl].maxx,p[kr].maxx);
    }
    int query(int k,int l,int r)
    {
        if(p[k].l>=l && p[k].r<=r)
            return p[k].maxx;
        int kl=k<<1,kr=kl+1,mid=(p[k].l+p[k].r)>>1;
        int a=0,b=0;
        if(l<=mid) a=query(kl,l,r);
        if(r>mid) b=query(kr,l,r);
        return max(a,b);
    }
    int main()
    {
        while(scanf("%d",&n)==1)
        {
            ms.clear();
            for(int i=0;i<n;i++)
            {
                scanf("%d %d",&h[i],&g[i]);
                ms[h[i]]=10;
            }
            map<int,int>::iterator it=ms.begin();
            int t=1;
            for(;it!=ms.end();it++)
                it->second=t++;
            bulid(1,t,1);
            dp[0]=g[0];
            update(1,ms[h[0]],dp[0]);
            int ans=dp[0];
            for(int i=1;i<n;i++)
            {
                if(ms[h[i]]!=1)
                    dp[i]=query(1,1,ms[h[i]]-1)+g[i];
                else dp[i]=g[i];
                update(1,ms[h[i]],dp[i]);
                ans=max(ans,dp[i]);
            }
            printf("%d\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    图论基础
    降维和聚类系列(二):拉普拉斯特征映射Laplacian Eigenmaps,谱聚类,实例代码
    降维和聚类系列(一):方法综述和比较(持续更新中)
    markdown设置图片尺寸
    指示向量indicator vector
    Sherlock and his girlfriend CodeForces
    The Meeting Place Cannot Be Changed CodeForces
    The Meeting Place Cannot Be Changed CodeForces
    数组分块入门 3
    数组分块入门 3
  • 原文地址:https://www.cnblogs.com/nanke/p/2446007.html
Copyright © 2011-2022 走看看