HDU 6447 YJJ's Salesman (dp+树状数组+莫干山算法)

题意:一个 1e9*1e9的方格,从(0,0)走到(1e9,1e9),有个方格有价值,特殊的经过方格可获得价值,每次只能向右、下、右下走,只有右下走到方格的才能获得价值,问最大获得的价值是多少

官方题解:莫干山算法(逃

个人理解:

先把各个村庄离散化,然后按照从上到下,从右到左的顺序排序,以上下为主,左右为次,之后我们更新这个 f [ j ] ,由于每一列的最大值只能由上一行影响,所以更新的顺序应该是从上到下,从左向右,类似01背包的优化。我们遍历的时候直接从第一个村庄遍历到最后一个村庄,由于已经排好序,所以在遍历的过程中可实现自动换行遍历,用数状数组取得f [ j - 1 ]的值,更新f [ j ]。

ps:后来发现不离散化这题也能过,数据出了问题。

代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define mod 1000000007
#define lowbit(x) (x&(-x))
#define mem(a,b) memset(a,b,sizeof(a))
#define FRER() freopen("in.txt","r",stdin);
#define FREW() freopen("out.txt","w",stdout);

using namespace std;

typedef pair<int,int> pii;
const int maxn = 100000 + 7, inf = 0x3f3f3f3f ;
struct Node{
    int x,y,v;
    bool operator < (const Node& rhs) const {
        return x == rhs.x ? y > rhs.y : x < rhs.x;
    }
}nodes[maxn];
int c[maxn];
void add(int x,int val){
    while(x < maxn){
        c[x] = max(c[x],val);
        x += lowbit(x);
    }
}
int query(int x){
    int res = 0;
    while(x){
        res = max(res,c[x]);
        x -= lowbit(x);
    }
    return res;
}

void Init(){
    mem(c,0),mem(nodes,0);
}

int main() {
    //FRER();
    //FREW();
    int T;
    scanf("%d",&T);
    while(T--){
        Init();
        int n;
        scanf("%d",&n);
        int cnt1 = 0 , cnt2 = 0;
        for(int i=1;i<=n;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            nodes[cnt2++] = {a,b,c};
        }
        sort(nodes,nodes+n);
        for(int i=0;i<n;i++){
            int val = query(nodes[i].y-1);
            add(nodes[i].y,val+nodes[i].v);
        }
        int res = query(n);
        cout<<res<<endl;
    }
    return 0;
}

  

posted @ 2018-08-25 22:21  dslybyme7  阅读(123)  评论(0编辑  收藏  举报