QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#736677#2582. 物理实验propane0 1359ms8752kbC++206.2kb2024-11-12 12:27:042024-11-12 12:27:09

Judging History

你现在查看的是最新测评结果

  • [2024-11-12 12:27:09]
  • 评测
  • 测评结果:0
  • 用时:1359ms
  • 内存:8752kb
  • [2024-11-12 12:27:04]
  • 提交

answer

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<numeric>
#include<cmath>
#include<set>
#include<iomanip>
#include<array>
using namespace std;
using LL = long long;

template<typename T>
T sign(T x){
    if (x > 0) return 1;
    if (x < 0) return -1;
    return 0;
}

template<typename T>
T abs(T x){
    if (x < 0) x = -x;
    return x;
}

template<typename T> 
T gcd(T a, T b){
    if (b == 0) return a;
    return gcd(b, a % b);
}

struct Point{
    long double x, y;

    Point operator+(const Point &t) const {
        return {x + t.x, y + t.y};
    }

    Point operator-(const Point &t) const {
        return {x - t.x, y - t.y};
    }

    Point operator*(long double t) const {
        return {x * t, y * t};
    }

    Point operator/(long double t) const {
        return {x / t, y / t};
    }

    long double operator*(const Point &t) const {
        return x * t.x + y * t.y;
    }

    long double operator^(const Point &t) const {
        return x * t.y - y * t.x;
    }

    long double len(){
        return sqrtl(x * x + y * y);
    }

};

struct Fraction{
    LL x, y; __int128_t v;
    long double val;

    // _x * _x / y
    Fraction(LL _x, LL _y){
        val = _x / sqrtl(_y);
        __int128_t t = __int128_t(_x) * _x * sign(_x);
        v = t / _y;
        x = t % _y;
        y = _y;
        LL g = abs(gcd(x, y));
        x /= g; y /= g;
    }

    bool operator<(const Fraction &t) const {
        if (v != t.v) return v < t.v;
        return __int128_t(x) * t.y < __int128_t(y) * t.x;
    }

    bool operator==(const Fraction &t) const {
        return v == t.v and x == t.x and y == t.y;
    }

};

long double cur_x;

struct Segment{
    Point a, b;

    long double k() const {
        return (b - a).len() / (b.x - a.x);
    }

    bool operator<(const Segment& t) const {
        long double y1 = a.y + (cur_x - a.x) / (b.x - a.x) * (b.y - a.y);
        long double y2 = t.a.y + (cur_x - t.a.x) / (t.b.x - t.a.x) * (t.b.y - t.a.y);
        return abs(y1) < abs(y2);
    }

};

struct Event{
    Fraction t; int id, type;

    bool operator<(const Event &a) const {
        if (t == a.t) return type < a.type;
        return t < a.t;
    }
};

int main(){

#ifdef LOCAL
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif

    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    cout << fixed << setprecision(10);

    int T;
    cin >> T;
    while(T--){
        int n;
        cin >> n;
        vector<array<LL, 4> > p(n);
        for(int i = 0; i < n; i++){
            for(auto &x : p[i]){
                cin >> x;
            }
        }
        LL x1, y1, x2, y2, L;
        cin >> x1 >> y1 >> x2 >> y2 >> L;
        LL dx = x2 - x1, dy = y2 - y1;
        LL sqr = dx * dx + dy * dy;
        Point v1 = {1.0L * dx, 1.0L * dy};
        v1 = v1 / v1.len();
        Point v2 = v1;
        swap(v2.x, v2.y);
        v2.x = -v2.x;
        vector<Segment> seg(n);
        vector<Fraction> nums;
        vector<Event> event;
        nums.reserve(2 * n);
        event.reserve(2 * n);
        for(int i = 0; i < n; i++){
            auto [x3, y3, x4, y4] = p[i];
            vector<Fraction> q;
            {
                LL dot = (x3 - x1) * dx + (y3 - y1) * dy;
                q.push_back(Fraction(dot, sqr));
                nums.push_back(q.back());
            }
            {
                LL dot = (x4 - x1) * dx + (y4 - y1) * dy;
                q.push_back(Fraction(dot, sqr));
                nums.push_back(q.back());
            }
            if (q[1] < q[0]){
                swap(q[0], q[1]);
                swap(x3, x4);
                swap(y3, y4);
            }
            Point p1 = {1.0L * x3 - x1, 1.0L * y3 - y1};
            Point p2 = {1.0L * x4 - x1, 1.0L * y4 - y1};
            seg[i] = {{p1 * v1, p1 * v2}, {p2 * v1, p2 * v2}};
            event.push_back({q[0], i, 1});
            event.push_back({q[1], i, 0});
        }
        sort(nums.begin(), nums.end());
        nums.erase(unique(nums.begin(), nums.end()), nums.end());

        sort(event.begin(), event.end());

        vector<long double> sum(nums.size() - 1);
        vector<long double> len(nums.size() - 1);

        set<Segment> st[2];

        for(int i = 0, j = 0; i + 1 < nums.size(); i++){
            len[i] = nums[i + 1].val - nums[i].val;
            cur_x = (nums[i].val + nums[i + 1].val) / 2;
            while(j < event.size() and (event[j].t == nums[i] and event[j].type == 0)){
                auto [_, id, type] = event[j++];
                st[seg[id].a.y > 0].erase(seg[id]);
            }
            while(j < event.size() and (event[j].t == nums[i] and event[j].type == 1)){
                auto [_, id, type] = event[j++];
                st[seg[id].a.y > 0].insert(seg[id]);
            }

            for(int k = 0; k < 2; k++){
                if (!st[k].empty()){
                    sum[i] += st[k].begin()->k() * len[i];
                }
            }
        }

        long double ans = 0, val = 0;
        for(int i = 0, j = 0; i + 1 < nums.size(); i++){
            if (i - 1 >= 0){
                val -= sum[i - 1];
            }
            while(j + 1 < nums.size() and nums[j + 1].val - nums[i].val <= L){
                val += sum[j++];
            }
            long double cur = val;
            if (nums[j].val - nums[i].val < L and j + 1 < nums.size()){
                cur += (L - (nums[j].val - nums[i].val)) / len[j] * sum[j];
            }
            ans = max(ans, cur);
        }
        val = 0;
        for(int i = nums.size() - 1, j = nums.size() - 1; i >= 1; i--){
            if (i < sum.size()){
                val -= sum[i];
            }
            while(j - 1 >= 0 and nums[i].val - nums[j - 1].val <= L){
                val += sum[--j];
            }
            long double cur = val;
            if (nums[i].val - nums[j].val < L and j - 1 >= 0){
                cur += (L - (nums[i].val - nums[j].val)) / len[j - 1] * sum[j - 1];
            }
            ans = max(ans, cur);
        }
        cout << ans << '\n';
    }

}

详细


Pretests


Final Tests

Test #1:

score: 0
Wrong Answer
time: 9ms
memory: 3872kb

input:

100
100
7143 -4407 6148 -4332
-3698 1987 -3674 2827
-2240 -6374 -3784 -6054
149 599 327 597
-2580 -4497 -2820 -4347
9219 -1818 6904 502
-5893 1341 -4357 -1890
-3503 -3287 -1087 -1211
-1579 7118 -229 7556
6456 502 1926 -1748
540 6714 -528 6825
1561 8432 -701 8357
422 6998 -41 7462
-1793 3676 1602 517...

output:

939.7746773737
454.2962581289
270.0970128690
17809.9325628679
693.6338490484
649.8851852460
17296.0296134399
1046.5194485707
1243.7315426742
620.6825537524
1320.0566275082
19054.0406513415
1062.0222738142
684.4295601859
421.1793537617
1051.7111712395
850.6338037141
22608.7457029564
13436.1931537422
...

result:

wrong answer wrong answer, 4th numbers differ - expected: '17826.678624', found: '17809.932563', error = '0.000939'

Test #2:

score: 0
Wrong Answer
time: 1193ms
memory: 8752kb

input:

100
10000
954303 48690 -14339 924721
464270 12166 -1609 433494
873644 42682 -12246 843861
449837 10414 -1919 418980
537496 14550 -6578 506603
552080 15962 -6594 521226
870138 42252 -12332 840332
57161 -702218 -671596 -43163
38907 -433607 -402515 -34409
445719 9913 -1981 414808
399734 5765 -1530 3686...

output:

23150.5368732009
1591692.1833796127
21928.6043845337
2894.6608545557
14332.0000008225
10772.2001200399
61378.5752461989
113952.2762085194
34711.4113561906
54764.0787161393
76852.1224785747
91593.0419494202
5004.1045959033
79872.5168546984
69493.4970644497
90559.4047765714
86547.5955539096
17134.6650...

result:

wrong answer wrong answer, 12th numbers differ - expected: '87090.617837', found: '91593.041949', error = '0.051698'

Test #3:

score: 0
Wrong Answer
time: 1359ms
memory: 8692kb

input:

100
10000
-636684471 -90006000 664665488 86376811
-263230447 -307903883 362658164 -223073366
-575841687 -121133860 614287459 40176834
-258935135 -268238570 347975250 -185982857
-287828480 -521064727 443096738 -422002609
-315452625 -391084040 435133968 -289354496
-560776752 -215271244 624810954 -5458...

output:

13997587.6583819207
17046702.4199334485
46390075.5222895952
7797517.4204758823
24229463.2094078694
13387746.9424728360
11290240.3043025049
55253758.7425349576
60559802.1793472293
80996320.5440268661
16696606.0002884474
18751679.4997104278
76860841.8119304551
22030848.0532682162
97322766.4551357781
2...

result:

wrong answer wrong answer, 15th numbers differ - expected: '68197919.173785', found: '97322766.455136', error = '0.427064'