以每个点为中心,极角排序,扫描线,用set维护当前极角下的线段集合,因为三角形不相交,所以set里面线段的相对顺序不会变。当扫到一个点的时候,看set里面离原点最近的线段会不会挡住当前点。
TLE卡了很久,发现point构造函数里面不要获取极角,因为三角函数atan2很慢。在有需要的时候再获取
还有一个小技巧是三角形的三条边实际上只有一条有用,因为点不会在三角形内部。
另外,下午在做另外一个题的时候,卡了atan2极角排序,坐标范围在1e9,所以可以构造数据卡极角排序(long double也没有用)。因为在第一象限,用叉积排序就好。以后可以用叉积排序就用叉积排,三角函数好慢啊!!!
留个东西
#include
using namespace std;
#define LL long long
#define pii pair
#define MP make_pair
#define ls i << 1
#define rs ls | 1
#define md (ll + rr >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define mod 1000000007
#define inf 0x3f3f3f3f
#define Pi acos(-1.0)
#define eps 1e-12
#define N 6020
#define M 400020
char buf[12000000],*pt = buf,*o = buf;
int getint(){
int f = 1,x = 0;
while((*pt != '-') && (*pt < '0' || *pt > '9')) pt ++;
if(*pt == '-') f = -1,pt ++; else x = *pt++ - 48;
while(*pt >= '0' && *pt <= '9') x = x * 10 + *pt ++ - 48;
return x * f;
}
char getch(){
char ch;
while(*pt < 'A' || *pt > 'Z') pt ++;
ch=*pt;pt++;
return ch;
}
int dcmp(double x){
if(fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
int sgn(LL x){
if(x == 0) return 0;
return x < 0 ? -1 : 1;
}
struct point{
double x, y, ang;
point(double x = 0, double y = 0) : x(x), y(y) {}
point operator - (const point &b) const {
return point(x - b.x, y - b.y);
}
point operator + (const point &b) const {
return point(x + b.x, y + b.y);
}
point operator * (const double &k) const {
return point(x * k, y * k);
}
bool operator < (const point &b) const {
return ang < b.ang;
}
bool operator == (const point &b) const {
return x == b.x && y == b.y;
}
double len(){
return sqrt(x * x + y * y);
}
void get_ang(){
ang = atan2(y, x);
}
void input(){
int xx, yy;
scanf("%d%d", &xx, &yy);
x = 1.0 * xx, y = 1.0 * yy;
}
};
double dot(point a, point b){
return a.x * b.x + a.y * b.y;
}
double cross(point a, point b){
return a.x * b.y - a.y * b.x;
}
point get_intersection(point a1, point a2, point b1, point b2){
point u = a1 - b1, av = a2 - a1, bv = b2 - b1;
double t = cross(bv, u) / cross(av, bv);
return a1 + av * t;
}
const point O = point(0, 0);
point base;
struct Seg{
point u, v;
int id, in;
double ang;
Seg(){}
Seg(point u, point v, int in, int id, double ang) : u(u), v(v), in(in), id(id), ang(ang) {}
bool operator < (const Seg &b) const {
if(u == b.u){
return cross(v - u, b.v - u) < 0;
}
point aa = get_intersection(u, v, O, base);
point bb = get_intersection(b.u, b.v, O, base);
return aa.len() < bb.len();
}
}L[N];
bool cmp(Seg a, Seg b){
return dcmp(a.ang - b.ang) < 0 || dcmp(a.ang - b.ang) == 0 && a.in > b.in;
}
int all, tot;
multiset S;
multiset ::iterator it[N];
point pp[N], p[N];
point tri[N][3], t[N][3];
void add(point u, point v, int id){
if(u.ang > v.ang) swap(u, v);
L[all++] = Seg(u, v, 1, id, u.ang);
L[all++] = Seg(v, u, 0, id, v.ang);
}
double calc(Seg s){
point a = get_intersection(s.u, s.v, O, base);
return a.len();
}
int solve(int n){
sort(p, p + n);
sort(L, L + all, cmp);
S.clear();
int ret = 0, i = 0, j = 0;
for(; i < n; ++i){
while(j < all && (dcmp(L[j].ang - p[i].ang) < 0 || (dcmp(L[j].ang - p[i].ang) == 0 && L[j].in))){
base = L[j].u;
if(L[j].in)
it[L[j].id] = S.insert(L[j]);
else
S.erase(it[L[j].id]);
++j;
}
if(S.empty()){
++ret; continue;
}
base = p[i];
double dis = calc(*S.begin());
if(dcmp(p[i].len() - dis) <= 0) ++ret;
}
// printf("size %d\n", S.size());
return ret;
}
int main(){
//fread(buf, 1, 12000000, stdin);
int V, T;
scanf("%d%d", &V, &T);
for(int i = 1; i <= V; ++i)
pp[i].input();
for(int i = 1; i <= T; ++i)
for(int j = 0; j < 3; ++j)
tri[i][j].input();
int ans = 0;
for(int i = 1; i <= V; ++i){
int cnt = 0;
for(int j = i + 1; j <= V; ++j){
p[cnt++] = pp[j] - pp[i];
p[cnt-1].get_ang();
}
tot = all = 0;
for(int j = 1; j <= T; ++j){
for(int k = 0; k < 3; ++k)
t[j][k] = tri[j][k] - pp[i];
t[j][3] = t[j][0];
point u, v;
double mx = 0;
for(int k = 0; k < 3; ++k){
double ang = dot(t[j][k], t[j][k+1]) / t[j][k].len() / t[j][k+1].len();
ang = acos(ang);
if(ang > mx)
mx = ang, u = t[j][k], v = t[j][k+1];
}
u.get_ang(), v.get_ang();
double d = fabs(u.ang - v.ang);
if(d < Pi)
add(u, v, tot++);
else{
point tmp = get_intersection(u, v, O, point(-1.0, 0));
tmp.ang = Pi * dcmp(u.ang);
add(u, tmp, tot++);
tmp.ang = Pi * dcmp(v.ang);
add(v, tmp, tot++);
}
}
int ret = solve(cnt);
// printf("%.2f %.2f %d\n", pp[i].x, pp[i].y, ret);
ans += ret;
}
printf("%d\n", ans);
return 0;
}