http://codeforces.com/contest/545/problem/C
题意:
给你n棵树{x,h} x是其坐标,h是高度
现在如果砍下第xi棵树,那么你可以让她往左倒下或者往右倒下, 这会形成一个区间[xi - hi, xi] or [xi;xi + hi]. .
能砍下这棵树的条件就是, 砍下之后形成的区间不包含任何别的树
思路:
贪心解决,从左到右贪心,先判断 【x-h,x】、【x,x+h】里是否有树
如果前者没,则说明可以往左倒,后者没,则可以往右倒
(我们要尽量让树往左倒,这样才能尽量得到最优解)
可以往左倒时,如果前面的树往左倒,则当前的树一定可以往左倒,否则,如果满足前面的树倒下的区间和当前的树倒下的区间不重合,也可以往左,其余就不可以了
当所有往左的情况都不合法时,那么只能往右倒或者无法倒了
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
struct node
{
int x,h,num;
int dir;
node(){}
node(int a,int b,int c)
{x=a;h=b;num=c;}
};
int kill[100005];
int min(int a,int b)
{
return a<b?a:b;
}
node tm[100005];
int main()
{
int i,j,n;
scanf("%d",&n);
for (i=1;i<=n;i++)
{
scanf("%d%d",&tm[i].x,&tm[i].h);
}
for (i=1;i<=n;i++)
{
int f=tm[i].x;
int d=tm[i].h;
int cun1=0;
int cun2=0;
j=i+1;
if (j<=n&&tm[j].x<=f+d)
{
cun1=1;
}
j=i-1;
if (j>=1&&tm[j].x>=f-d)
{
cun2=1;
}
if (!cun2&&!cun1)
{
if (i==1) {tm[i].dir=1;continue;}
if (tm[i-1].dir==1||!tm[i-1].dir)
tm[i].dir=1;
else
if (tm[i-1].dir==2&&tm[i-1].x+tm[i-1].h<tm[i].x-tm[i].h )
tm[i].dir=1;
else
tm[i].dir=2;
}
else
if (cun2==0) //left
{
if (i==1) {tm[i].dir=1;continue;}
if (tm[i-1].dir==1||!tm[i-1].dir)//left
tm[i].dir=1;
else //前一个往右倒
{
if (tm[i-1].dir==2&&tm[i-1].x+tm[i-1].h<tm[i].x-tm[i].h) // 互不相压
tm[i].dir=1; //可以往左
else
kill[i]=1; //无法砍下
}
}
else
if (cun1==0) //right
{
tm[i].dir=2;
}
else
kill[i]=1; //无法砍下
}
int ans=0;
for (i=1;i<=n;i++)
{
if (kill[i]==0)
ans++;
}
printf("%d\n",ans);
return 0;
}