前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HDU6447(离散化扫描线+树状数组)

HDU6447(离散化扫描线+树状数组)

作者头像
ACM算法日常
发布2019-04-25 17:22:42
5540
发布2019-04-25 17:22:42
举报
文章被收录于专栏:ACM算法日常

几句话简谈题意:

YJJ要从(0,0)点走到(1e9,1e9),当他处于点(x,y)时他只能走到(x,y+1)或(x+1,y)或(x+1,y+1)。而坐标轴上有n个村庄,如果他路过某个村庄就会赚到特定数量的钱,可是处于点(xk,yk)的村庄只会跟从点(xk-1,yk-1)走过来的人交易。求YJJ走完旅途能得到的最大钱数。

(每步好几个可选、求最后的最大XX,一眼dp对吧)

输入格式:

第一行一个T(1 <= T <= 10),代表测试数据组数;

之后对于每组测试数据,第一行读入n(1 <= n <= 1e5),代表n个村庄;

接下来的n行每行三个数字x,y,value,表示这个村庄在点(x,y),如果你从(x-1,y-1)走过来的话就能和它做交易并得到value数量的钱。其中1 <= x, y <= 1e9,0 <= value <= 1e3。

输出格式:

每组数据一行一个数字,表示旅途走完后可以得到的最大钱数。

样例输入:

1

3

1 1 1

1 2 2

3 3 1

样例输出:

3

放这道题的本意:

上一期放了一个树状数组的题,但我觉得很可能有很多人并不会这个东西……然后这题作为一个小测试,上次不会的东西,回过头来自己找时间学了吗?有时候有缘遇到了不会的东西就不妨去学一学,否则下次遇到可能就是考场了。

一句话口胡题解:

还是一道比较常规的题目,大概会的人不用我讲,不会的人需要自学(啥玩意)。一些简单琐碎的点,不好讲。

一眼看过去就x排序扫描一下,y是1e9的离散化一下,每层用树状数组或者线段树维护一下,然后发现y正着扫不行对吧?像dp倒着循环似的树状数组把y倒着插就可行了。

然鹅这种意识流题解不可能看懂的……

自学标签:1.离散化;2.扫描线;3.树状数组;4.线段树(因为更常见的是用线段树维护);5.背包(大雾。01背包使用一维滚动数组时为什么要倒着扫你真的懂了吗?)

学完以上几个以后可以尝试这道题目了,后续推荐练习:BZOJ4653、BZOJ1218.

代码语言:javascript
复制
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>
#include <sstream>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <list>
#include <fstream>
#include <bitset>
#define init(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define irep(i, a, b) for (int i = a; i >= b; i--)
using namespace std;

typedef double db;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
const int inf = 0x3f3f3f3f;
const ll INF = 1e18;

template <typename T> void read(T &x) {
    x = 0;
    int s = 1, c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')    s = -1;
    for (; isdigit(c); c = getchar())
        x = x * 10 + c - 48;
    x *= s;
}

template <typename T> void write(T x) {
    if (x < 0)    x = -x, putchar('-');
    if (x > 9)    write(x / 10);
    putchar(x % 10 + '0');
}

template <typename T> void writeln(T x) {
    write(x);
    puts("");
}

const int maxn = 1e5 + 5;
int T, n;
struct cord {
    int x, y, v;

    bool operator < (const cord& rhs) const {
        if (x != rhs.x) return x < rhs.x;
        return y > rhs.y;
    }
}a[maxn];
int yy[maxn], tot;
struct BIT {//树状数组
    int F[maxn];

    void Update(int pos, int val) {
        for (; pos <= tot; pos += pos&-pos)
            F[pos] = max(F[pos], val);
    }

    int Query(int pos) {
        int ret = 0;
        for (; pos; pos -= pos&-pos)
            ret = max(ret, F[pos]);
        return ret;
    }
}bit;

int main() {
    for (read(T); T; T--, tot = 0) {
        read(n);
        rep(i, 1, n) {
            read(a[i].x);
            read(a[i].y);
            read(a[i].v);
            yy[++tot] = a[i].y;
        }
        //离散化
        sort(yy + 1, yy + 1 + tot);
        tot = unique(yy + 1, yy + 1 + tot) - yy - 1;
        rep(i, 1, n) {
            a[i].y = lower_bound(yy + 1, yy + 1 + tot, a[i].y) - yy;
        }
        //扫描插入,注意a的排序
        sort(a + 1, a + 1 + n);
        init(bit.F, 0);
        rep(i, 1, n) {
            bit.Update(a[i].y, bit.Query(a[i].y - 1) + a[i].v);
        }
        writeln(bit.Query(tot));
    }
    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ACM算法日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档