题目地址:http://vjudge.net/problem/UVALive-4253
二分x轴上的点,再用角度的区间表示能否射到
#include <bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(int i=a;i<=(int)(b);++i)
#define REPD(i,a,b) for(int i=a;i>=(int)(b);--i)
const double EPS=1e-6;
struct Target
{
double d,l,r;
bool operator < (const Target& t) const {
return d<t.d;
}
}tt[5000+5];
int n,w;
int Check(double x){
double L=atan2(tt[1].d,tt[1].r-x); //[L,R] 因为是逆时针的
double R=atan2(tt[1].d,tt[1].l-x);
REP(i,2,n){
double L1=atan2(tt[i].d,tt[i].r-x);
double R1=atan2(tt[i].d,tt[i].l-x);
if(L-R1>EPS) return -1; //[L,R] U [L1,R1] != 空集
if(L1-R>EPS) return 1;
L=max(L,L1);
R=min(R,R1);
}
return 0;
}
int main(int argc, char const *argv[])
{
int T; scanf("%d",&T);
while(T--){
scanf("%d%d",&w,&n);
REP(i,1,n) scanf("%lf%lf%lf",&tt[i].d,&tt[i].l,&tt[i].r);
sort(tt+1,tt+1+n);
bool ok=false;
double L=0,R=w;
while(R-L>EPS){
double mid=(L+R)/2;
int a=Check(mid);
if(a==0) {ok=true; break;}
else if(a==-1) R=mid; //点要向左边移动
else L=mid;
}
printf("%s\n", ok?"YES":"NO");
}
return 0;
}