【LittleXi】规划兼职工作

【LittleXi】规划兼职工作

题目链接

心路历程:

早上起来打开题目,一点思路没有
摆烂点开《戴森球》就到中午了,退出游戏,一眼线段树,直接秒了
总结:打游戏,也可以提高思维能力

解题思路

线段树+离散化+dp
离散化:因为时间太长(1e9)所以我们应该对时间排序,用顺序1、2、3来模拟时间次序
dp:将线段按第一个节点排序,对于到达每个节点的最大利润,可以从前面所有节点中的最大利润转移过来即nowprofit=前面所有节点中的最大利润+profit[now]
线段树:在寻找前面的最大利润是,我们可以想到用线段树寻找区间最大值
时间复杂度:O(nlogn)

代码


#define lc k<<1
#define rc k<<1|1

const int maxn = 500010;
const int inf = 0x3f3f3f3f;
int n, a[maxn];

struct node
{
    int l, r, mx;
};
node tree[maxn * 4];

void build(int k, int l, int r)//创建叶子节点,k表示存储下标,l,r表示更新区间
{
    tree[k].l = l;
    tree[k].r = r;
    if (l == r)
    {
        tree[k].mx = a[l];
        return;
    }
    int mid = (l + r) / 2;
    build(lc, l, mid);
    build(rc, mid + 1, r);
    tree[k].mx = max(tree[lc].mx, tree[rc].mx);
}

void update(int k, int i, int v)//点更新,将a[i]修改为v
{
    if (tree[k].l == tree[k].r && tree[k].l == i)
    {
        tree[k].mx = v;
        return;
    }
    int mid = (tree[k].l + tree[k].r) / 2;
    if (i <= mid)
        update(lc, i, v);
    else
        update(rc, i, v);
    tree[k].mx = max(tree[lc].mx, tree[rc].mx);
}

int query(int k, int l, int r)//区间覆盖查询,求区间[l,r]的最大值
{
    if (tree[k].l >= l && tree[k].r <= r)
        return tree[k].mx;
    int mid = (tree[k].l + tree[k].r) / 2;
    int ma = -inf;
    if (l <= mid)
        ma = max(ma, query(lc, l, r));
    if (r > mid)
        ma = max(ma, query(rc, l, r));
    return ma;
}


class Solution {
public:
    int jobScheduling(vector<int>& st, vector<int>& en, vector<int>& pr) {
        int n = st.size();
        vector<vector<int>> vec(n);
        set<int> lisan;
        for (int i = 0; i < n; i++)
        {
            lisan.insert(st[i]);
            lisan.insert(en[i]);
        }
        int p = 1;
        unordered_map<int, int> m;
        for (auto& val:lisan)
        {
            m[val] = p++;
        }
        for (int i = 0; i < n; i++)
        {
            vec[i].push_back(m[st[i]]);
            vec[i].push_back(m[en[i]]);
            vec[i].push_back(pr[i]);
        }
        sort(vec.begin(), vec.end(), [&](vector<int>& v1,
            vector<int>& v2) {return v1[0] < v2[0]; });
        memset(a, 0, sizeof(a));
        build(1, 0, 500005);
        for (int i = 0; i < n; i++)
        {
            int be = vec[i][0];
            int en = vec[i][1];
            int money = vec[i][2];
            int temp = query(1, 1, be);
            a[en] = max(a[en],temp + money);
            update(1, en, a[en]);
        }
        int re = *max_element(a, a + 500000);
        return re;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值