题目大意: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; }