hdu 3607 Traversal(树状数组+离散化)

Traversal

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 861    Accepted Submission(s): 306


Problem Description
Xiao Ming is travelling, and today he came to the West Lake, to see people playing a game, this game is like this, lake placed n-box, from 1 to n label. These boxes are floating in the water, there are some gold inside each box. Then participants from coast to jump the other side, each box have its’s height, you can only jump from lower height to higher height, and from a small label to a big label, you can skip some of the middle of the box. Suppose the minimum height is this side, the other side has the maximum height. Xiao Ming would like to jump how to get the most gold? He now needs your help.
 

Input
There are multiple test cases. Each test case contains one integer N , representing the number of boxes . The following N lines each line contains two integers hi and gi , indicate the height and the number of gold of the ith box.
1 < = N < 100 001
0 < hi < 100 000 001
0 < gi < = 10000
 

Output
For each test case you should output a single line, containing the number of maximum gold XiaoMing can get.

 

Sample Input
  
  
4 1 1 2 2 2 3 5 1 1 1 10000
 

Sample Output
  
  
5 10000


 

题意:有n个木箱,每个木箱都有一个高度和相应的黄金。现在要跳到木箱上取木箱的黄金,规定每次只能跳到比上一个木箱高的且标签大的木箱上。现在要求出最多能得到的黄金。

思路:容易想到用dp来做。按标签从前到后搜索,关键是每次找出比当前高度低的且黄金数是最多的状态,而这个状态可以用树状数组来找,树状数组c[i]保存的是已跳到高度为i的木箱时取得的最大黄金数。题目高度范围较大,所以要离散化,每次用二分找出离散化后某个高度对应的下标即可。记得每次都要更新树状数组。

 

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <stack>
#include <cstdlib>
#define L(rt) (rt<<1)
#define R(rt) (rt<<1|1)

using namespace std;

const int maxn=100005;
struct node
{
    int hi,gi,id;
}box[maxn];
int c[maxn],index[maxn],h[maxn];
int n,cnt;
int lowbit(int x)
{
    return x&(-x);
}
int query(int x)
{
    int ans=0;
    for(int i=x;i>0;i-=lowbit(i))
    ans=max(ans,c[i]);
    return ans;
}
void update(int x,int val)
{
    for(int i=x;i<=cnt;i+=lowbit(i))
    c[i]=max(c[i],val);
}
int binary(int x)
{
    int low=1,high=cnt,mid;
    while(low<=high)
    {
        mid=(low+high)>>1;
        if(h[mid]==x) return mid;
        else if(h[mid]<x) low=mid+1;
        else high=mid-1;
    }
    return -1;
}
int main()
{
    while(~scanf("%d",&n))
    {
        memset(c,0,sizeof(c));
        cnt=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&box[i].hi,&box[i].gi);
            if(binary(box[i].hi)==-1)
            h[++cnt]=box[i].hi;
        }
        sort(h+1,h+cnt+1);
        int ans=0,t,index;
        for(int i=1;i<=n;i++)
        {
            index=binary(box[i].hi);
            t=query(index-1);
            ans=max(ans,t+box[i].gi);
            update(index,t+box[i].gi);
        }
        printf("%d\n",ans);
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值