CodeForces

传送门

题目大意:n棵树(10^5),坐标xi,高度hi,把这棵树砍到,可以向右倒[xi,xi+hi]被占,

向左倒[xi-hi,xi]被占,必须要倒的坐标没有被占才能倒,不砍倒就xi被占,问最多砍几棵树。

题解:

比赛时没A,现在A了,刚睡醒做题智商还是在线的....

大多是贪心..我的方法应该不是贪心吧。

如果n>2

对于区间[Lp,Rp],

那么最左边Lp和最右边Rp的树分别向左倒,像右倒就可以。

然后现在需要处理的区间就变成了 [Lp+1,Rp-1].然后按之前的方法处理就可以,相当于范围缩小了嘛

左边向左倒,否则向右倒;右边向右倒,否则向左倒。

不断缩小区间就可以。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100009
using namespace std;

int ans;

int n,L,R,Lp,Rp;

int x[N],h[N];

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&h[i]);
    if(n==1) {cout<<"1";return 0;}
    if(n==2) {cout<<"2";return 0;}
    ans=2;L=x[1];R=x[n];Lp=2;Rp=n-1;
    while(Lp<=Rp)
    {
        if(Lp==Rp)
        {
            if(x[Lp]-h[Lp]>L||x[Lp]+h[Lp]<R) ans++;
            break;
        }
        bool flag1=0,flag2=0;
        if(x[Lp]-h[Lp]>L) 
        {
            flag1=true;
            ans++;
            L=x[Lp];
        }else
        if(x[Lp]+h[Lp]<x[Lp+1])
        {
            flag1=true;
            ans++;
            L=x[Lp]+h[Lp];
        }
        if(!flag1) L=x[Lp];
        Lp++;
    //    if(Lp>Rp) break;
        if(x[Rp]+h[Rp]<R)
        {
            flag2=true;
            ans++;
            R=x[Rp];
        }else
        if(x[Rp]-h[Rp]>x[Rp-1])
        {
            flag2=true;
            ans++;
            R=x[Rp]-h[Rp];
        }
        if(!flag2)R=x[Rp];
        Rp--;
    }
    cout<<ans<<endl;
    return 0;
} 
原文地址:https://www.cnblogs.com/zzyh/p/11946823.html