题目描述
你需要在一条无限长的道路上喷洒杀虫剂。
在这条道路上,总共有 N 个投放点,其中第 i 个投放点在数轴上坐标 pi 处。在每一个投放点,你可以选择往左喷洒或往右喷洒。但是由于风向和地理环境的影响,向左喷洒和向右喷洒的效果不一定相同。具体来说,在一个位置向左喷洒,可以覆盖 [pi - li, pi] 这一段区域,而向右喷洒可以覆盖 [pi, pi + ri] 这一段区域。
请你决定每个投放点是向左喷洒还是向右喷洒,来使得被杀虫剂覆盖的路段长度和最大。
输入描述:
第一行 N。
接下来 N 行,每行 pi, li, ri。
输出描述:
输出最大的被杀虫剂覆盖的长度和。
示例1
输入
4
1 2 2
3 3 3
4 3 3
6 2 2
输出
9
说明
让第一个和第三个投放点向左喷洒,其他投放点向右喷洒。
这样能覆盖的区域是
[
−
1
,
8
]
[-1,8]
[−1,8],总长度为 9。
备注:
对于测试点 1、2,N≤ 15;
对于测试点 3、4,N≤ 3,000, ri = 0;
对于测试点 5、6,N≤ 30;
对于测试点 7、8,N≤ 300;
对于测试点 9、10,N≤ 3,000;
保证 pi, li, ri ≤ 109。
思路:
代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=1e4;
struct node{int p,l,r;}a[N];
int n,cnt,b[N],id[N];
ll f[2][N];
inline bool cmp(node a,node b){return a.p<b.p;}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%d%d%d",&a[i].p,&a[i].l,&a[i].r);
b[++cnt]=a[i].p;
b[++cnt]=a[i].l=a[i].p-a[i].l;
b[++cnt]=a[i].r=a[i].p+a[i].r;
}
sort(b+1,b+cnt+1);
cnt=unique(b+1,b+cnt+1)-b-1;
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
a[i].p=lower_bound(b+1,b+cnt+1,a[i].p)-b;
a[i].l=lower_bound(b+1,b+cnt+1,a[i].l)-b;
a[i].r=lower_bound(b+1,b+cnt+1,a[i].r)-b;
id[a[i].p]=i;
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=cnt;++j)f[i&1][j]=f[(i-1)&1][j];
for(int j=a[i].l+1;j<=a[i].p;++j)f[i&1][j]=max(f[i&1][j],f[i&1][j-1]+b[j]-b[j-1]);
ll tmp=f[(i-1)&1][a[i].p];
for(int j=a[i].p+1;j<=a[i].r;++j)
{
f[i&1][j]=max(f[i&1][j],tmp+b[j]-b[a[i].p]);
if(id[j]&&a[id[j]].l<a[i].p)tmp=max(tmp,f[(i-1)&1][a[id[j]].l]+b[a[i].p]-b[a[id[j]].l]);
}
for(int j=2;j<=cnt;++j)f[i&1][j]=max(f[i&1][j],f[i&1][j-1]);
}
printf("%lld",f[n&1][cnt]);
}
来源:nkw