#1964 : 最大房租(线段树+DP)

博客围绕小Hi在AirBnb上出租房间的预约问题展开,已知租金为每天100元,有N个预约,需完整接受且不能有日期重叠,要计算最多能收到的租金。思路是用动态规划(DP),dp[i]表示第i分钟结束的最大值,还可借助线段树查询,后续更新提到用树状数组更好。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

小Hi有一个房间在AirBnb上出租,租金是每天100元。

现在他一共收到了N个预约,其中第i个预约的时间是第Si天到第Ei天。

显然预约必须被完整接受,不能只接受其中部分天数;并且小Hi不能接受有冲突(日期重叠)的预约。

请你帮小Hi计算他最多收到多少租金?

输入

第一行包含一个整数N。  

以下N行每行包含两个整数Si和Ei。  

1 <= N <= 100000 0 <= Si <= Ei <= 1000000

输出

一个整数代表答案

样例输入

5
1 3
4 6
7 9
3 101
4 100

样例输出

10000

 

思路:显然贪心不行 考虑DP dp[i]表示第i分钟结束的最大值,给输入排序 ,

dp【a[i].e】等于 max( dp【a[i].e】,max(dp[1]~dp[a[i].s-1])+第i个的长度),max(dp[1]~dp[a[i].s-1])可以用线段树查询

update:此题用树状数组做更好写,常数更小

 

代码

#include<bits/stdc++.h>
#define LL long long
#define pi pair<int,int>
using namespace std;
const int maxn = 2e6+10;
const int mod = 1e9+7;
struct node
{
    LL l,r;
    LL mx;
}tree[maxn<<2];
pi a[maxn];
int dp[maxn];
void pushup(LL rt)
{
    tree[rt].mx=max(tree[rt<<1].mx,tree[rt<<1|1].mx);
}
void build(LL l,LL r,LL rt)
{
    tree[rt].l=l;
    tree[rt].r=r;
    if(tree[rt].l==tree[rt].r)
    {
        tree[rt].mx=0;
        return ;
    }
    LL mid=(l+r)>>1;
    build(l,mid,rt*2);
    build(mid+1,r,rt*2+1);
    pushup(rt);
}
void update(LL x,LL v,LL rt)
{
    if(tree[rt].l==tree[rt].r)
    {
        tree[rt].mx=max(v,tree[rt].mx);
        return ;
    }
    LL mid=(tree[rt].l+tree[rt].r)>>1;
    if(x>=mid+1)
    {
        update(x,v,rt*2+1);
    }
    else if(x<=mid)
    {
        update(x,v,rt*2);
    }
    pushup(rt);
}
LL query(LL l,LL r,LL rt)
{
    //cout<<l<<" "<<r<<" "<<tree[rt].sum<<endl;
    if(l==tree[rt].l&&r==tree[rt].r)
    {
        return tree[rt].mx;
    }
    if(l>tree[rt].r||r<tree[rt].l)
        return 0;
    LL mid=(tree[rt].l+tree[rt].r)>>1;
    if(r<=mid)
    {
        return query(l,r,rt*2);
    }
    else if(l>=mid+1)
    {
        return query(l,r,rt*2+1);
    }
    else
    {
        return max(query(l,mid,rt*2),query(mid+1,r,rt*2+1));
    }
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&a[i].first,&a[i].second);
    }
    sort(a,a+n);
    build(1,1000010,1);
    for(int i=0;i<n;i++)
    {
        dp[i]=max(dp[i],a[i].second-a[i].first+1);
        if(a[i].first>1)
        {
            dp[i]=max(1LL*dp[i],query(1,a[i].first-1,1)+a[i].second-a[i].first+1);

        }
        update(a[i].second,dp[i],1);
    }
    int ans=0;
    for(int i=0;i<1000010;i++)
    {
        ans=max(ans,dp[i]);
    }
    printf("%d\n",ans*100);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值