HDU 6447 YJJ’s Salesman (树状数组 + DP + 离散)

题意:

二维平面上N个点,从(0,0)出发到(1e9,1e9),每次只能往右,上,右上三个方向移动, 
该N个点只有从它的左下方格点可达,此时可获得收益。求该过程最大收益。

分析:我们很容易就可以想到用DP,假设这个位置是相对上一个位置的方向而来,但是复杂度达到N^2 ,这样是不行的;

我们可以利用坐标的信息,将所有的点离散化后,以x优先按小到大排序,按y按大到小排序,这时维护一个DP(i) ,表示第I列的最值。

j=0→i?1j=0→i?1 
                          dp[i]←max(dp[i[,dp[j]+val)dp[i]←max(dp[i[,dp[j]+val)

因为x已经按从小到大排好序了,y也是从大到小更新的,故保证了可达性。

对于每次更新,可以用线段树或者树状数组维护最大值,此时算法复杂度O(NlogN)

#include<bits/stdc++.h>
using namespace std;
int n,hashx[100001],hashy[100001],dp[100001],tree[100001];
struct no
{
    int x,y,w;
}a[100001];
bool cmp(no a, no b)
{
    if(a.x==b.x)
    return a.y>b.y;
    return a.x<b.x;

}
//离散化
void init( )
{
    for(int i=1 ; i<=n ; i++)
    {
        hashx[i] = a[i].x;
        hashy[i] = a[i].y;
    }
    sort(hashx+1,hashx+1+n);
    sort(hashy+1,hashy+1+n);
     int cntx = unique(hashx+1,hashx+1+n)-hashx;
     int cnty = unique(hashy+1,hashy+1+n)-hashy;
    for(int i=1 ; i<=n ; i++)
    {
        a[i].x = lower_bound(hashx+1,hashx+1+cntx,a[i].x)-hashx;
        a[i].y = lower_bound(hashy+1,hashy+1+cnty,a[i].y)-hashy;
    }

}
int lowbit(int x)
{
    return x&(-x);
}
void update(int pos)
{
    while(pos <= n)
    {
        tree[pos] = dp[pos];
        for(int i=1;i<lowbit(pos);i<<=1)
            tree[pos] = max(tree[pos],tree[pos-i]);
        pos += lowbit(pos);
    }
}

int query(int l, int r)
{
    int ans = 0;
    while(r>=l)
    {
        ans = max(ans,dp[r]);
        if(l==r)    break;
        for(--r;r-l>=lowbit(r);r-=lowbit(r))
            ans = max(ans,tree[r]);
    }
    return ans;
}
int main( )
{
    int t;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&n);
        for(int i=1 ; i<=n ; i++)
        {
            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
        }
        sort(a+1,a+1+n,cmp);
        init( );
        memset(dp,0,sizeof(dp));
        memset(tree,0,sizeof(tree));
        for(int i=1 ; i<=n ; i++)
        {
            dp[a[i].y]=max(dp[a[i].y],query(1,a[i].y-1)+a[i].w);
            update(a[i].y);

        }
        int ans = 0;
        for(int i=1;i<=n;++i)
            ans = max(ans,dp[i]);
        printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/shuaihui520/p/9536982.html

时间: 2024-10-13 17:08:41

HDU 6447 YJJ’s Salesman (树状数组 + DP + 离散)的相关文章

HDU 6447 - YJJ&#39;s Salesman - [树状数组优化DP][2018CCPC网络选拔赛第10题]

Problem DescriptionYJJ is a salesman who has traveled through western country. YJJ is always on journey. Either is he at the destination, or on the way to destination.One day, he is going to travel from city A to southeastern city B. Let us assume th

hdu 2227Find the nondecreasing subsequences(树状数组+dp+离散化)

题目链接:点击打开链接 题意描述:给定一个序列,找出其中递增子序列的数量? 解题思路: 1.dp[i]:表示以元素i结尾的子序列的数量,则d[j]=sum(d[i])+1;其中(j>=i且j的下标大于i) 2.此刻我们可以联想到树状数组,按数组下标从小到大的顺序插入元素,那么d[j]就等于sum(j)+1; 3.由于数据范围比较大,我们采用离散化处理即可 代码: #include <cstdio> #include <algorithm> #include <cstri

[HDU 6447][YJJ&#39;s Salesman][2018CCPC网络选拔赛 1010][离散化+线段树+DP]

链接: http://acm.hdu.edu.cn/showproblem.php?pid=6447 题意: 左上角(0,0),右下角(10^9,10^9)的网格,其中有n(1<=n<=10^5)个方格内有权值. 一次只能沿右,下,右下三个方向走一个格子,只有沿右下方向走到格子里才可以获得权值. 问从(0,0)到(10^9,10^9)的路径最大权值是多少. 思路: 网格路径权值问题,第一感考虑DP,x从上往下,y从左往右刷表,状态转移方程为dp[i][j]=max(dp[i-1][j],dp[

hdu 3015 Disharmony Trees (离散化+树状数组)

Disharmony Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 663    Accepted Submission(s): 307 Problem Description One day Sophia finds a very big square. There are n trees in the square. T

HDU 2852 KiKi&#39;s K-Number (树状数组 &amp;&amp; 二分)

题意:给出对容器的总操作次数n, 接下来是这n个操作.这里对于一个容器提供三种操作, 分别是插入.删除和查找.输入0  e表示插入e.输入1  e表示删除e,若元素不存在输出No Elment!.输入2  e  k表示查找比e大且第k大的数, 若不存在则输出Not Find! 分析:这里考虑树状数组做的原因是在第三个操作的时候, 只要我们记录了元素的总数, 那通过求和操作, 便能够高效地知道到底有多少个数比现在求和的这个数要大, 例如 tot - sum(3)就能知道整个集合里面比3大的数到底有

HDU 3584 Cube (三维 树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3584 Cube Problem Description Given an N*N*N cube A, whose elements are either 0 or 1. A[i, j, k] means the number in the i-th row , j-th column and k-th layer. Initially we have A[i, j, k] = 0 (1 <= i, 

hdu 3030 Increasing Speed Limits (离散化+树状数组+DP思想)

Increasing Speed Limits Time Limit: 2000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 481    Accepted Submission(s): 245 Problem Description You were driving along a highway when you got caught by the road p

HDU 5592 ZYB&#39;s Premutation(树状数组+二分)

题意:给一个排列的每个前缀区间的逆序对数,让还原 原序列. 思路:考虑逆序对的意思,对于k = f[i] - f[i -1],就表示在第i个位置前面有k个比当前位置大的数,那么也就是:除了i后面的数字之外,它是在剩下的数字当中第k+1大的. 知道这个之后,可以用树状数组来帮助找出剩下的数中第k大的数,刚开始我们可以让1-n中每个元素都标记为1,那么他们的前缀和就代表它是第几小.所以,我们可以对于他们的和来二分快速寻找第k大数.其实在树状数组里面是按照第(i-k)小来找的.找完之后要删除这个元素的

hdu 5592 ZYB&#39;s Game 树状数组

ZYB's Game Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5592 Description ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutation,now he ask you to restore the premutation