Problem:
Problem G: Yu-kun Likes People Watching
Background
会津大学付属幼稚園はプログラミングが大好きな子供が集まる幼稚園である。園児の一人であるゆう君は、プログラミングと同じくらい人を観察することが大好きだ。
そんなゆう君は、去年の夏休みに作成した人の移動経路のデータと建物の位置情報を観察してあることを疑問に思った。
全ての人が建物内にいる時間の長さのうち、最長のものはどのくらいなのだろうか？
Problem
建物と人の移動経路の情報が与えられる。
全ての人が連続して建物内にいるような時間のうち、最も長いものの長さを出力せよ。
そのような時間が存在しない場合は長さは０とする。
建物と人はそれぞれ2次元平面上の多角形と点として表される。
人は単位時間あたり
x
軸方向と
y
軸方向にそれぞれ速度
vx
と
vy
で移動する。
人を表す点が建物を表す多角形内にある場合、その人は建物内にいるものとする。 
( 多角形の辺上に人がいる場合も建物内にいるものとする )
図1は、Sample Input 2 における建物と人の移動経路を表している。多角形は建物、黒い丸は人の初期位置、矢印はその人の移動経路を表す。
時刻2から時刻4、時刻9から時刻12の間に人は建物内にいるため、建物内に全ての人がいる時間の最長は3となる。
図１: Sample Input 2
Input
n
m
T
建物0の情報
建物1の情報
...
建物
n-1
の情報
人0の移動経路
人1の移動経路
...
人
m-1
の移動経路
n
,
m
,
T
はそれぞれ建物を表す多角形の数、人の数、人が移動する時間の上限を表す。
建物の情報は以下のような形式で与えられる。
(
x
i
,
y
i
)と(
x
i+1
,
y
i+1
)の頂点を繋いだ線分が多角形の一辺である。ただし、
p-1
番目の頂点とは、0番目の頂点が繋がる。
p
x
0
y
0
x
1
y
1
...
x
p-1
y
p-1
人の経路情報は以下のような形式で与えられる。
t
0
sx
0
sy
0
(
t
0
= 0 )
t
1
vx
1
vy
1
t
2
vx
2
vy
2
...
t
k
vx
k
vy
k
(
t
k
=
T
)
人は2次元平面上を移動する。 (
sx
0
,
sy
0
) は人が時刻0にいる位置である。
時刻
t
i-1
から
t
i
の間( 0 <
i
≤
k
),
x
軸方向と
y
軸方向にそれぞれ速度
vx
i
と
vy
i
で移動する。
Constraints
入力は以下の条件を満たす。
入力は全て整数として与えられる
1 ≤
n
,
m
≤ 10
3 ≤
p
≤ 10
1 ≤
T
≤ 3600
0 ≤
x
,
y
,
sx
,
sy
≤ 1000
0 =
t
0
<
t
1
< ... <
t
k
=
T
-10 ≤
vx
1
,
vy
1
,...,
vx
k
,
vy
k
≤ 10
建物を表す多角形は時計回りまたは反時計周りで与えられる
多角形の連続する３つの頂点は、一直線上に並ばないものとする
人の位置は常に0以上1000以下である
同じ時刻に2人以上の人が同じ座標にいても良い
建物が別の建物を内包するようなことはない
建物を表す多角形の辺が別の建物を表す多角形の辺と共通な部分をもつことはない
Output
全ての人が建物内にいるような時間のうち、その長さが最長のものの長さを1行で出力せよ。
そのような時間がない場合、長さは０とする。
小数点以下は何桁数字を出力しても構わない。ただし、解答の誤差は0.000001(10
-6
)を超えてはならない。
Sample Input 1
1 1 10
4 3 0 7 0 7 10 3 10
0 0 5
10 1 0
Sample Output 1
4.0000000000
Sample Input 2
1 1 14
4 2 3 6 3 6 6 2 6
0 0 4
3 1 0
6 0 -1
7 1 0
10 0 1
14 1 0
Sample Output 2
3.0000000000
Sample Input 3
2 2 7
4 2 2 5 2 5 5 2 5
4 7 2 10 2 10 5 7 5
0 0 4
3 1 0
7 0 -1
0 7 7
2 1 0
5 0 -1
7 1 0
Sample Output 3
1.0000000000
Sample Input 4
1 3 10
9 2 3 3 6 4 3 5 6 6 3 7 6 8 3 8 7 2 7
0 1 5
10 1 0
0 11 4
10 -1 0
0 4 8
6 0 -1
8 1 0
10 0 1
Sample Output 4
0.3333333333
Sample Input 5
1 2 7
4 2 1 6 1 6 5 2 5
0 1 4
7 1 0
0 9 3
7 0 1
Sample Output 5
0.0000000000

Submitted solutions:

code_snippet: // AOJ #1547 Yu-kun Likes People Watching
// 2025.3.29

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const double EPS = 1e-9;

bool inPoly(double x, double y, const vector<pair<double,double>> &poly) {
    int cnt = 0;
    int sz = poly.size();
    for (int i = 0; i < sz; i++) {
        auto [x1, y1] = poly[i];
        auto [x2, y2] = poly[(i+1)%sz];
        double cross = (x - x1)*(y2 - y1) - (y - y1)*(x2 - x1);
        if (fabs(cross) < EPS && min(x1,x2) - EPS <= x && x <= max(x1,x2) + EPS &&
            min(y1,y2) - EPS <= y && y <= max(y1,y2) + EPS)
            return true;
        bool cond1 = (y1 <= y && y < y2) || (y2 <= y && y < y1);
        if(cond1) {
            double xint = x1 + (y - y1) * (x2 - x1) / (y2 - y1);
            if(x < xint) cnt++;
        }
    }
    return (cnt % 2) == 1;
}

struct Intv { double s, e; };

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n, m, T;
    cin >> n >> m >> T;
    vector<vector<pair<double,double>>> bld(n);
    for(int i=0;i<n;i++){
        int p;
        cin >> p;
        bld[i].resize(p);
        for (int j = 0; j < p; j++) cin >> bld[i][j].first >> bld[i][j].second;
    }

    vector<vector<Intv>> P(m);
    for(int i=0;i<m;i++){
        double t0, sx, sy;
        cin >> t0 >> sx >> sy;
        double cur_t = t0, cur_x = sx, cur_y = sy;
        vector<Intv> iv;
        while(true) {
            double nt, vx, vy;
            if(!(cin >> nt >> vx >> vy)) break;
            double st = cur_t, ed = nt;
            vector<double> ev;
            ev.push_back(st);
            ev.push_back(ed);
            for(auto &poly : bld) {
                int sz = poly.size();
                for (int j = 0; j < sz; j++){
                    double ax = poly[j].first, ay = poly[j].second;
                    double bx = poly[(j+1)%sz].first, by = poly[(j+1)%sz].second;
                    double dX = bx - ax, dY = by - ay;
                    double D = vy*dX - vx*dY;
                    if(fabs(D) < EPS) continue;
                    double dt = ( - (ax - cur_x)*dY + (ay - cur_y)*dX ) / D;
                    double u  = ( vx*(ay - cur_y) - vy*(ax - cur_x) ) / D;
                    if(dt < -EPS || dt > ed - st + EPS) continue;
                    if(u < -EPS || u > 1+EPS) continue;
                    double t_int = st + dt;
                    if(t_int < st - EPS || t_int > ed + EPS) continue;
                    ev.push_back(t_int);
                }
            }
            sort(ev.begin(), ev.end());
            ev.erase(unique(ev.begin(), ev.end(), [&](double a, double b){ return fabs(a-b) < EPS; }), ev.end());
            for (size_t k=0; k+1 < ev.size(); k++){
                double a = ev[k], b = ev[k+1];
                if(b - a < EPS) continue;
                double mid = (a+b)/2;
                double x = cur_x + vx*(mid - st);
                double y = cur_y + vy*(mid - st);
                bool inside = false;
                for(auto &poly : bld) {
                    if(inPoly(x,y, poly)) { inside = true; break; }
                }
                if(inside)
                    iv.push_back({a, b});
            }
            cur_x += vx*(ed - st);
            cur_y += vy*(ed - st);
            cur_t = ed;
            if(fabs(cur_t - T) < EPS) break;
        }
        sort(iv.begin(), iv.end(), [](const Intv &a, const Intv &b){ return a.s < b.s; });
        vector<Intv> mv;
        for(auto &e: iv) {
            if(mv.empty() || e.s > mv.back().e + EPS) mv.push_back(e);
            else                   mv.back().e = max(mv.back().e, e.e);
        }
        P[i] = mv;
    }

    vector<Intv> cur = P[0];
    for (int i = 1; i < m; i++){
        vector<Intv> nxt;
        int a = 0, b = 0;
        while(a < cur.size() && b < P[i].size()){
            double s = max(cur[a].s, P[i][b].s);
            double e = min(cur[a].e, P[i][b].e);
            if(e - s > EPS) nxt.push_back({s, e});
            if(cur[a].e < P[i][b].e) a++;
            else b++;
        }
        cur = nxt;
    }
    double ans = 0;
    for(auto &e: cur) ans = max(ans, e.e - e.s);
    cout << fixed << setprecision(10) << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3724
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
#include <assert.h>

using namespace std;

template<typename T>
struct Point{
    T x,y;
    
    Point(T x, T y):x(x), y(y){}
    Point(){}
    template<typename Y>
    Point(const Point<Y>& pt):x(pt.x), y(pt.y){}
    
    Point operator-(const Point& other)const{
        return Point(x-other.x, y-other.y);
    }
    
    T operator%(const Point& other) const {
        return x * other.y - y * other.x;      
    }
    
    T operator*(const Point& other) const {
        return x * other.x + y * other.y;      
    }
    Point operator*(T v) const {
        return Point(x * v, y * v);      
    }
    
    void print(){
        cout << "(" << x << "," << y << ") ";    
    }
};

template<typename T>
T area(Point<T> a, Point<T> b, Point<T> c){
    return (c-a)%(b-a);        
}

typedef vector<Point<long long int> > polygon;

long long int area(const polygon& p){
    long long int ans = 0;
    
    for (int i=1;i+1<p.size();i++){
        ans += area(p[0], p[i], p[i+1]);    
    }
    
    return ans;
}


template<typename T>
bool on_segment(Point<T> a, Point<T> b, Point<T> c){
    return area(a,b,c) == 0 && (c-b)*(a-b) <= 0;
}


template<typename T> bool inside_triangle(Point<T> a, Point<T> b, Point<T> c, Point<T> x){
    T area_ = abs(area(a,b,c));
    T area1 = abs(area(a,b,x)) + abs(area(b,c,x)) + abs(area(a,c,x));
    
    return area_ == area1;
}

template<> bool inside_triangle(Point<double> a, Point<double> b, Point<double> c, Point<double> x){
    double area_ = abs(area(a,b,c));
    double area1 = abs(area(a,b,x)) + abs(area(b,c,x)) + abs(area(a,c,x));
    
    return abs(area_ - area1) < 1e-8; 
}

vector<polygon> triangulize(const polygon& p){
    int n = p.size();
    
    long long int area_sign = area(p) > 0 ? 1 : -1;
    
    if (n == 3){
        if ((p[2]-p[0]) % (p[1]-p[0]))
            return {p};    
        else
            return {};
    }
    
    for (int i=0;i<n;i++){
        int j = (i+1)%n, jj = (i+n-1)%n;
        
        long long int triangle_area_sign = area(p[jj],p[i], p[j]) > 0 ? 1 :-1;
        
        auto ok = [&](){
            for (int x=0;x<n;x++){
                if (x != i && x != j && x != jj){
                    if (inside_triangle(p[jj], p[i], p[j], p[x])){
                        return false;
                    }
                }
            }
            return true;
        };
        
        if (triangle_area_sign == area_sign){
            if (ok()){
                polygon q;
                for (int x=0;x<n;x++){
                    if (x != i){
                        q.push_back(p[x]);        
                    }
                }
                auto tri = triangulize(q);


                if ((p[i]-p[j]) % (p[jj]-p[j]))
                    tri.push_back({p[jj], p[i], p[j]});
                
                
                return tri;
            }
        }
        
        
    }
}

double cross(Point<long long int> A, Point<long long int> B, Point<long long int> X, Point<long long int> Y){
    if (  ((B-A)%(X-A))   *   ((B-A)%(Y-A)) <= 0  && ((X-Y)%(A-Y))   *   ((X-Y)%(B-Y)) < 0 ){
        /*
        
        (B.y-A.y)x+(A.x-B.x)y-(B.y-A.y)B.x-(A.x-B.x)B.y=0
        (Y.y-X.y)x+(X.x-Y.x)y-(Y.y-X.y)Y.x-(X.x-Y.x)Y.y=0

        ax+by+c=0
        dx+ey+f=0

        y = (cd-af)/(ae-bd)
        x = (ce-bf)/(ae-bd)
        

        */
       
        long long int a = B.y - A.y, b = A.x - B.x, c = -((B.y-A.y)*B.x+(A.x-B.x)*B.y);
        long long int d = Y.y - X.y, e = X.x - Y.x, f = -((Y.y-X.y)*Y.x+(X.x-Y.x)*Y.y);

        double yy = (c*d-a*f)/(e*1.0*a-b*1.0*d);
        double xx = (b*f-c*e)/(e*1.0*a-b*1.0*d);

        if (abs(yy-A.y) > 1e-7){
            return (yy-A.y)/(B.y-A.y);
        } else {
            return (xx-A.x)/(B.x-A.x);
        }

    } else {
        return -1;
    }
}

int T;

pair<double,double> entrance(long long int t1, long long int t2, Point<long long int> A, Point<long long int> B, const polygon& p){
    bool insideA = inside_triangle(p[0], p[1], p[2], A);
    bool insideB = inside_triangle(p[0], p[1], p[2], B);

    if (insideA && insideB) return {-!!t1, t2 == T ? T : -1};

    if (insideA ^ insideB){
        Point<double> aa(A), bb(B), p0(p[0]), p1(p[1]), p2(p[2]);
        double l = 0, r = 1;

        for (int t=0;t<70;t++){
            double m = (l+r)/2;
            Point<double> mm = aa - (bb-aa) * (-m);

            if (insideA == inside_triangle(p0,p1,p2,mm))
                l = m;
            else
                r = m;

        }

        if (insideA){
            return {-!!t1, t1 + (t2-t1) * r};
        } else {
            return {t1 + (t2-t1) * l, t2 == T ? T : -1};
        }

    } else {
        double cross1 = cross(A,B,p[0], p[1]);
        double cross2 = cross(A,B,p[1], p[2]);
        double cross3 = cross(A,B,p[2], p[0]);

        vector<double> crosses;

        if (cross1 != -1) crosses.push_back(t1 + (t2-t1)*cross1);
        if (cross2 != -1) crosses.push_back(t1 + (t2-t1)*cross2);
        if (cross3 != -1) crosses.push_back(t1 + (t2-t1)*cross3);

        assert(crosses.size() != 1);

        if (crosses.empty())
            return {-1, -1};

        sort(crosses.begin(), crosses.end());
        
        return {crosses[0], crosses.back()};

    }

}

struct event{
    double t;
    int who;
    bool entered;

    bool operator<(const event& other){
        return t < other.t;
    }
};

int main(){
    int n,m;
    cin >> n >> m >> T;

    vector<polygon> triangles;

    for (int i=0;i<n;i++){
        polygon p;
        int k;
        cin >> k;

        for (int i=0;i<k;i++){
            int x,y;
            cin >> x >> y;

            p.push_back(Point<long long int>(x, y));
        }

        for (auto &tri:triangulize(p)) {
            triangles.push_back(tri);
        }
    }

    vector<event> events;


    for (int i=0;i<m;i++){
        long long int t0, x,y;
        cin >> t0 >> x >> y;

        while(1){
            long long int t,vx,vy;
            cin >> t >> vx >> vy;

            Point<long long int> A(x, y);
            Point<long long int> B(x + vx * (t-t0), y + vy * (t-t0));

            for (auto &tri:triangles){
                auto [enter, leave] = entrance(t0, t, A, B, tri);

                if (enter != -1){ 
                    events.push_back(event{enter-1e-8, i, 1});
                }
                if (leave != -1){

                    events.push_back(event{leave+1e-8, i, 0});
                }

            }

            if (t == T){
                break; 
            } else {
                x = x + vx * (t-t0);
                y = y + vy * (t-t0);
                t0 = t;
            }
        }

    }

    vector<int> people_inside(m,0);
    sort(events.begin(), events.end());
    
    double ans = 0;
    double consec_inside = 0;
    double L = 0;

    for (auto &e:events){
        bool inside_before = 1;
        for (auto &x:people_inside)
            if (!x)
                inside_before = 0;

        
        if (inside_before){
            consec_inside += e.t - L;
            ans = max(ans, consec_inside);
        } else {
            consec_inside = 0;
        }

        if (e.entered)
            ++people_inside[e.who];
        else
            --people_inside[e.who];

        L = e.t;
    }

    cout << std::fixed << setprecision(11) << ans << endl;

}
accuracy: 1
time_ms: 90
memory_kb: 4184
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
#include <assert.h>

using namespace std;

template<typename T>
struct Point{
    T x,y;
    
    Point(T x, T y):x(x), y(y){}
    Point(){}
    template<typename Y>
    Point(const Point<Y>& pt):x(pt.x), y(pt.y){}
    
    Point operator-(const Point& other)const{
        return Point(x-other.x, y-other.y);
    }
    
    T operator%(const Point& other) const {
        return x * other.y - y * other.x;      
    }
    
    T operator*(const Point& other) const {
        return x * other.x + y * other.y;      
    }
    Point operator*(T v) const {
        return Point(x * v, y * v);      
    }
    
    void print(){
        cout << "(" << x << "," << y << ") ";    
    }
};

template<typename T>
T area(Point<T> a, Point<T> b, Point<T> c){
    return (c-a)%(b-a);        
}

typedef vector<Point<long long int> > polygon;

long long int area(const polygon& p){
    long long int ans = 0;
    
    for (int i=1;i+1<p.size();i++){
        ans += area(p[0], p[i], p[i+1]);    
    }
    
    return ans;
}


template<typename T>
bool on_segment(Point<T> a, Point<T> b, Point<T> c){
    return area(a,b,c) == 0 && (c-b)*(a-b) <= 0;
}


template<typename T> bool inside_triangle(Point<T> a, Point<T> b, Point<T> c, Point<T> x){
    T area_ = abs(area(a,b,c));
    T area1 = abs(area(a,b,x)) + abs(area(b,c,x)) + abs(area(a,c,x));
    
    return area_ == area1;
}

template<> bool inside_triangle(Point<double> a, Point<double> b, Point<double> c, Point<double> x){
    double area_ = abs(area(a,b,c));
    double area1 = abs(area(a,b,x)) + abs(area(b,c,x)) + abs(area(a,c,x));
    
    return abs(area_ - area1) < 1e-8; 
}

vector<polygon> triangulize(const polygon& p){
    int n = p.size();
    
    long long int area_sign = area(p) > 0 ? 1 : -1;
    
    if (n == 3){
        if ((p[2]-p[0]) % (p[1]-p[0]))
            return {p};    
        else
            return {};
    }
    
    for (int i=0;i<n;i++){
        int j = (i+1)%n, jj = (i+n-1)%n;
        
        long long int triangle_area_sign = area(p[jj],p[i], p[j]) > 0 ? 1 :-1;
        
        auto ok = [&](){
            for (int x=0;x<n;x++){
                if (x != i && x != j && x != jj){
                    if (inside_triangle(p[jj], p[i], p[j], p[x])){
                        return false;
                    }
                }
            }
            return true;
        };
        
        if (triangle_area_sign == area_sign){
            if (ok()){
                polygon q;
                for (int x=0;x<n;x++){
                    if (x != i){
                        q.push_back(p[x]);        
                    }
                }
                auto tri = triangulize(q);


                if ((p[i]-p[j]) % (p[jj]-p[j]))
                    tri.push_back({p[jj], p[i], p[j]});
                
                
                return tri;
            }
        }
        
        
    }
}

double cross(Point<long long int> A, Point<long long int> B, Point<long long int> X, Point<long long int> Y){
    if (  ((B-A)%(X-A))   *   ((B-A)%(Y-A)) <= 0  && ((X-Y)%(A-Y))   *   ((X-Y)%(B-Y)) < 0 ){
        /*
        
        (B.y-A.y)x+(A.x-B.x)y-(B.y-A.y)B.x-(A.x-B.x)B.y=0
        (Y.y-X.y)x+(X.x-Y.x)y-(Y.y-X.y)Y.x-(X.x-Y.x)Y.y=0

        ax+by+c=0
        dx+ey+f=0

        y = (cd-af)/(ae-bd)
        x = (ce-bf)/(ae-bd)
        

        */
       
        long long int a = B.y - A.y, b = A.x - B.x, c = -((B.y-A.y)*B.x+(A.x-B.x)*B.y);
        long long int d = Y.y - X.y, e = X.x - Y.x, f = -((Y.y-X.y)*Y.x+(X.x-Y.x)*Y.y);

        double yy = (c*d-a*f)/(e*1.0*a-b*1.0*d);
        double xx = (b*f-c*e)/(e*1.0*a-b*1.0*d);

        if (abs(yy-A.y) > 1e-7){
            return (yy-A.y)/(B.y-A.y);
        } else {
            return (xx-A.x)/(B.x-A.x);
        }

    } else {
        return -1;
    }
}

int T;

pair<double,double> entrance(long long int t1, long long int t2, Point<long long int> A, Point<long long int> B, const polygon& p){
    bool insideA = inside_triangle(p[0], p[1], p[2], A);
    bool insideB = inside_triangle(p[0], p[1], p[2], B);

    if (insideA && insideB) return {-!!t1, t2 == T ? T : -1};

    if (insideA ^ insideB){
        Point<double> aa(A), bb(B), p0(p[0]), p1(p[1]), p2(p[2]);
        double l = 0, r = 1;

        for (int t=0;t<70;t++){
            double m = (l+r)/2;
            Point<double> mm = aa - (bb-aa) * (-m);

            if (insideA == inside_triangle(p0,p1,p2,mm))
                l = m;
            else
                r = m;

        }

        if (insideA){
            return {-!!t1, t1 + (t2-t1) * r};
        } else {
            return {t1 + (t2-t1) * l, t2 == T ? T : -1};
        }

    } else {
        double cross1 = cross(A,B,p[0], p[1]);
        double cross2 = cross(A,B,p[1], p[2]);
        double cross3 = cross(A,B,p[2], p[0]);

        vector<double> crosses;

        if (cross1 != -1) crosses.push_back(t1 + (t2-t1)*cross1);
        if (cross2 != -1) crosses.push_back(t1 + (t2-t1)*cross2);
        if (cross3 != -1) crosses.push_back(t1 + (t2-t1)*cross3);

        assert(crosses.size() != 1);

        if (crosses.empty())
            return {-1, -1};

        sort(crosses.begin(), crosses.end());
        
        return {crosses[0], crosses.back()};

    }

}

struct event{
    double t;
    int who;
    bool entered;

    bool operator<(const event& other){
        return t < other.t;
    }
};

int main(){
    int n,m;
    cin >> n >> m >> T;

    vector<polygon> triangles;

    for (int i=0;i<n;i++){
        polygon p;
        int k;
        cin >> k;

        for (int i=0;i<k;i++){
            int x,y;
            cin >> x >> y;

            p.push_back(Point<long long int>(x, y));
        }

        for (auto &tri:triangulize(p)) {
            triangles.push_back(tri);
        }
    }

    vector<event> events;


    for (int i=0;i<m;i++){
        long long int t0, x,y;
        cin >> t0 >> x >> y;

        while(1){
            long long int t,vx,vy;
            cin >> t >> vx >> vy;

            Point<long long int> A(x, y);
            Point<long long int> B(x + vx * (t-t0), y + vy * (t-t0));

            for (auto &tri:triangles){
                auto [enter, leave] = entrance(t0, t, A, B, tri);

                if (enter != -1){ 
                    events.push_back(event{enter-1e-8, i, 1});
                }
                if (leave != -1){

                    events.push_back(event{leave+1e-8, i, 0});
                }

            }

            if (t == T){
                break; 
            } else {
                x = x + vx * (t-t0);
                y = y + vy * (t-t0);
                t0 = t;
            }
        }

    }

    vector<int> people_inside(m,0);
    sort(events.begin(), events.end());
    
    double ans = 0;
    double consec_inside = 0;
    double L = 0;

    for (auto &e:events){
        bool inside_before = 1;
        for (auto &x:people_inside)
            if (!x)
                inside_before = 0;

        
        if (inside_before){
            consec_inside += e.t - L;
            ans = max(ans, consec_inside);
        } else {
            consec_inside = 0;
        }

        if (e.entered)
            ++people_inside[e.who];
        else
            --people_inside[e.who];

        L = e.t;
    }

    cout << setprecision(11) << ans << endl;

}
accuracy: 0.9117647058823529
time_ms: 90
memory_kb: 4048
final_rank: 4

code_snippet: #include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

// ==================================================================== Geometry Library ====================================================================
struct Point {
	long double px, py;
};

Point operator+(const Point& a1, const Point& a2) {
	return Point{ a1.px + a2.px, a1.py + a2.py };
}

Point operator-(const Point& a1, const Point& a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

Point operator*(const Point& a1, const long double& a2) {
	return Point{ a1.px * a2, a1.py * a2 };
}

bool operator<(const Point& a1, const Point& a2) {
	if (a1.px < a2.px) return true;
	return false;
}

// ノルム
long double norm(Point p) {
	return p.px * p.px + p.py * p.py;
}

// 距離
long double dist(Point p) {
	return sqrt(norm(p));
}

// 内積
long double dot(Point p1, Point p2) {
	return p1.px * p2.px + p1.py * p2.py;
}

// 外積
long double crs(Point p1, Point p2) {
	return p1.px * p2.py - p1.py * p2.px;
}

// 交点を求める
pair<bool, Point> Intersection(Point a1, Point a2, Point b1, Point b2) {
	long double p1 = crs(b1 - a1, a2 - a1);
	long double p2 = crs(b2 - a1, a2 - a1);
	long double p3 = crs(a1 - b1, b2 - b1);
	long double p4 = crs(a2 - b1, b2 - b1);
	if (p1 > 0 && p2 > 0) return make_pair(false, Point{ 0.0, 0.0 });
	if (p1 < 0 && p2 < 0) return make_pair(false, Point{ 0.0, 0.0 });
	if (p3 > 0 && p4 > 0) return make_pair(false, Point{ 0.0, 0.0 });
	if (p3 < 0 && p4 < 0) return make_pair(false, Point{ 0.0, 0.0 });
	if (p3 == p4) return make_pair(true, Point{ 1e9, 1e9 }); // 平行な場合のコーナーケース
	Point r = a1 + (a2 - a1) * ((0.0 - p3) / (p4 - p3));
	return make_pair(true, r);
}

// AOJ の ccw からコピー
int ccw(Point p1, Point p2, Point p3) {
	Point v1 = p2 - p1;
	Point v2 = p3 - p1;
	if (crs(v1, v2) > +1.0e-9L) return +1;
	if (crs(v1, v2) < -1.0e-9L) return -1;
	if (dot(v1, v2) < -1.0e-9L) return 2;
	if (norm(v1) < norm(v2)) return -2;
	return 0;
}

// 内部に入っているかの情報
bool Inside(vector<Point> Poly, Point P) {
	if (P.px == 6.0) {
		P.px += 0.0;
	}
	int N = Poly.size();
	int cnt = 0;
	for (int i = 0; i < N; i++) {
		Point v1 = (Poly[(i + 0) % N] - P);
		Point v2 = (Poly[(i + 1) % N] - P);
		if (abs(crs(v1, v2)) < 1.0e-9L && dot(v1, v2) < 1.0e-9L) return true;
		if (v1.py > v2.py) swap(v1, v2);
		if (v1.py < 1.0e-9L && v2.py > 1.0e-9L && crs(v1, v2) > 1.0e-9L) cnt += 1;
	}
	if (cnt % 2 == 1) return true;
	return false;
}


// ==================================================================== Main Part ====================================================================
int N; vector<Point> Build[19];
int M; vector<pair<long double, Point>> Move[19];
int Sum[1 << 19];
vector<pair<long double, long double>> Range[19][19];
vector<pair<long double, long double>> Range2[19];
long double T;

vector<pair<long double, long double>> Hantei(vector<Point> Poly, vector<pair<long double, Point>> Human) {
	vector<pair<long double, Point>> Cand;

	// 交点を列挙
	for (int i = 0; i < Human.size(); i++) Cand.push_back(Human[i]);
	for (int i = 0; i < Human.size() - 1; i++) {
		Point p1 = Human[i + 0].second;
		Point p2 = Human[i + 1].second;
		for (int j = 0; j < Poly.size(); j++) {
			Point v1 = Poly[(j + 0) % Poly.size()];
			Point v2 = Poly[(j + 1) % Poly.size()];
			pair<bool, Point> ret = Intersection(v1, v2, p1, p2);
			if (ret.first == false) continue;
			if (ret.second.px > 1e8) {
				long double tm1 = Human[i + 0].first + (Human[i + 1].first - Human[i + 0].first) * dist(v1 - p1) / dist(p1 - p2);
				long double tm2 = Human[i + 0].first + (Human[i + 1].first - Human[i + 0].first) * dist(v2 - p1) / dist(p1 - p2);
				if (dist(p1 - v1) < dist(p1 - p2) && dist(p2 - v1) < dist(p1 - p2)) Cand.push_back(make_pair(tm1, v1));
				if (dist(p1 - v2) < dist(p1 - p2) && dist(p2 - v1) < dist(p1 - p2)) Cand.push_back(make_pair(tm1, v2));
			}
			else {
				long double tm1 = Human[i + 0].first + (Human[i + 1].first - Human[i + 0].first) * dist(ret.second - p1) / dist(p1 - p2);
				Cand.push_back(make_pair(tm1, ret.second));
			}
		}
	}
	sort(Cand.begin(), Cand.end());

	// 中に入っている区間を求める
	vector<pair<long double, long double>> vec;
	for (int i = 0; i < Cand.size() - 1; i++) {
		Point p1 = Cand[i + 0].second;
		Point p2 = Cand[i + 1].second;
		Point md = (p1 + p2) * 0.5L;
		if (Inside(Poly, md) == false) continue;
		vec.push_back(make_pair(Cand[i + 0].first, Cand[i + 1].first + 1.0e-9L));
	}
	return vec;
}

int main() {
	// Step 1. Input
	cin >> N >> M >> T;
	for (int i = 0; i < N; i++) {
		int p; cin >> p;
		for (int j = 0; j < p; j++) {
			long double ex, ey; cin >> ex >> ey;
			Build[i].push_back(Point{ ex, ey });
		}
	}
	for (int i = 0; i < M; i++) {
		long double sx = 0, sy = 0;
		while (true) {
			long double t, ex, ey; cin >> t >> ex >> ey;
			if (Move[i].size() == 0) { sx = ex; sy = ey; }
			else { long double tm = t - Move[i][Move[i].size() - 1].first; sx += ex * tm; sy += ey * tm; }
			Move[i].push_back(make_pair(t, Point{ sx, sy }));
			if (t == T) break;
		}
	}

	// Step 2. Enumerate
	for (int i = 0; i < M; i++) {
		for (int j = 0; j < N; j++) Range[i][j] = Hantei(Build[j], Move[i]);
	}

	// Step 3. Get Range
	for (int i = 0; i < M; i++) {
		vector<pair<long double, long double>> r;
		for (int j = 0; j < N; j++) {
			for (int k = 0; k < Range[i][j].size(); k++) r.push_back(Range[i][j][k]);
		}
		sort(r.begin(), r.end());
		if (r.size() == 0) continue;
		long double lft = r[0].first, maxn = -1.0;
		for (int j = 0; j < r.size(); j++) {
			maxn = max(maxn, r[j].second);
			if (j == r.size() - 1 || maxn < r[j + 1].first) {
				Range2[i].push_back(make_pair(lft, maxn));
				if (j != r.size() - 1) lft = r[j + 1].first;
			}
		}
	}

	// Step 4. Compression
	vector<long double> Zahyou;
	for (int i = 0; i < M; i++) {
		for (int j = 0; j < Range2[i].size(); j++) Zahyou.push_back(Range2[i][j].first);
		for (int j = 0; j < Range2[i].size(); j++) Zahyou.push_back(Range2[i][j].second);
	}
	sort(Zahyou.begin(), Zahyou.end());
	Zahyou.erase(unique(Zahyou.begin(), Zahyou.end()), Zahyou.end());
	for (int i = 0; i < M; i++) {
		for (int j = 0; j < Range2[i].size(); j++) {
			int pos1 = lower_bound(Zahyou.begin(), Zahyou.end(), Range2[i][j].first) - Zahyou.begin();
			int pos2 = lower_bound(Zahyou.begin(), Zahyou.end(), Range2[i][j].second) - Zahyou.begin();
			Sum[pos1] += 1;
			Sum[pos2] -= 1;
		}
	}
	for (int i = 1; i <= Zahyou.size(); i++) Sum[i] += Sum[i - 1];

	// Step 5. Get Answer
	long double Answer = 0;
	long double Cons = 0;
	for (int i = 0; i < (int)Zahyou.size() - 1; i++) {
		if (Sum[i] != M) { Cons = 0; continue; }
		Cons += (Zahyou[i + 1] - Zahyou[i]);
		Answer = max(Answer, Cons);
	}
	printf("%.12Lf\n", Answer);
	return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 6412
final_rank: 3