您的位置:首页 > 其它

[Noip模拟题]砍树

2017-10-09 17:49 197 查看
Description

小A在一条水平的马路上种了n棵树,过了几年树都长高大了,每棵树都可以看作是一条长度为ai的竖线段。由于有的树过于高大,挡住了其他的树,使得另外一些树得不到阳光。如果有两棵树i,j。i顶端与j底端连线的倾角大于45度,我们就定义为i挡住了j。现在小A希望将一些树砍低,使得不存在挡住的情况。他想知道总共最少需要砍掉多少长度,请你来帮他计算一下。注意,如果同一位置有两棵树德话,根据题意,我们只能将这两棵树都砍成高度为0才能保证它们不相互挡住,但是高度为0并不代表这棵树不存在。

Input

第一行一个正整数n,表示有n棵树。

接下来n行,每行两个正整数pi,ai,表示一棵树的位置和高度。

n<=100000;0<=pi,ai<=10000

Output

输出一个数,表示最少砍断多少长度。

Sample Input

3

0 2

1 2

3 3

Sample Output

3

HINT

思路

一棵树i能被另一棵树j挡住,当且仅当abs(pi−pj)<=aj。由于答案只与一个位置是否有树和这棵树的高度有关,而不与树的序号有关,因此,可以记录每个位置的树的高度,如果有两棵树在同一个位置,那么将这一个位置的树的高度变为0,将这两棵树的高度都计入答案。枚举时就寻找是否有满足上面条件的树,处理一下计入答案。这道题就完美的被解决了。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn=10000;

int h[maxn+10],n,ans;

int main()
{
memset(h,255,sizeof h);
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(h[a]!=-1)
{
ans+=h[a]+b;
h[a]=0;
}
else
{
h[a]=b;
}
}
for(int i=0; i<=maxn; i++)
{
int r=h[i];
if(h[i]!=-1)
{
for(int j=std::max(i-h[i],0); j<=std::min(i+h[i],maxn); j++)
{
if((h[j]!=-1)&&(j!=i))
{
r=std::min(r,abs(j-i));
}
}
}
ans+=h[i]-r;
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: