时间限制: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;
}