QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#820448#4601. Vale of EternalSGColinAC ✓44ms6568kbC++2010.2kb2024-12-18 21:28:402024-12-18 21:28:40

Judging History

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

  • [2024-12-18 21:28:40]
  • 评测
  • 测评结果:AC
  • 用时:44ms
  • 内存:6568kb
  • [2024-12-18 21:28:40]
  • 提交

answer

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

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define pii pair<int, int>
#define rep(i, x, y) for (int i = (x); i <= (y); ++i)
#define per(i, x, y) for (int i = (x); i >= (y); --i)

inline ll rd() {
    ll x = 0;
    bool f = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) f |= (c == '-');
    for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    return f ? -x : x;
}

typedef long long T;
#define let const auto
#define lett const T
#define letp const P // P for point
#define lets const S // S for segment
#define letl const L // L for line
#define letc const C // C for convex

#define z(x) (abs((x)) <= eps) // is zero

const T eps = 1e-8;
constexpr double PI=3.1415926535897932384;
struct P {
    T x, y;
    P (T x = 0, T y = 0) : x(x), y(y) {}
    P operator + (letp &p) const {return {x + p.x, y + p.y};} 
    P operator - (letp &p) const {return {x - p.x, y - p.y};} 
    P operator * (lett &d) const {return {x * d, y * d};}
    P operator / (lett &d) const {return {x / d, y / d};}
    P operator - () const {return {-x, -y};}

    T operator | (letp &p) const {return x * p.x + y * p.y;} // dot
    T operator ^ (letp &p) const {return x * p.y - y * p.x;} // cross
    
    // P rot(double ang) const { // counterclockwise rotation (ang) angle
    //     double cosa = cos(ang), sina = sin(ang);
    //     return {x * cosa - y * sina, x * sina + y * cosa};
    // }

    bool operator == (letp &p) const {return z(x - p.x) && z(y - p.y);}
    bool operator != (letp &p) const {return ! operator == (p);}
    bool operator < (letp &p) const {return z(x - p.x) ? y < p.y : x < p.x;}
    bool operator > (letp &p) const {return !(*this < p || *this == p);}
   
    // left(counterclockwise) = 1 | on = 0 | right(clockwise) = -1
    int ori(letp &p) const {T t = (*this) ^ p; return (t > eps) - (t < -eps);}

    T norm() const {return x * x + y * y;}
    P proj (letp &p) const {return (*this) * (((*this) | p) / norm());}
    P refl (letp &p) const {return proj(p) * 2 - p;}

    void print() const {printf("%lld %lld\n", x, y);}

} zero;

double abs(letp &p) {return sqrt(p.norm());}
P normalize(letp &p) {return p / abs(p);}
P perp(letp &p) {return {-p.y, p.x};} // turn pi / 2 left
P perpr(letp &p) {return {p.y, -p.x};} // turn pi / 2 right

bool orth(letp &p, letp &q) {return (p | q) == 0;}
bool para(letp &p, letp &q) {return (p ^ q) == 0;}

struct argcmp { // compared by polar angle
    bool operator() (letp &a, letp &b) const {
        const auto quad = [](letp &a) {
            if (a.y < -eps) return 1; // halfplane with negative y
            if (a.y > eps) return 4;  // halfplane with positive y
            if (a.x < -eps) return 5; // negative x-axis
            if (a.x > eps) return 3;  // positive x-axis
            return 2; // origin
        };
        const int qa = quad(a), qb = quad(b);
        if (qa != qb) return qa < qb; 
        const auto t = a ^ b; //in the same quad
        // sorted by length in increasing order when parallel
        // if (z(t)) return norm(a) < norm(b) - eps; 
        return t > eps;
    }    
};

struct L {
    P p, v; 
    int ori (letp &a) const {return v.ori(a - p);} 
    P inter(letl &l) const {return p + v * ((l.v ^ (p - l.p)) / (v ^ l.v));} 
    L shift(letp &d) const {return {p + d, v};}
    L shiftl(double d) const {return {p + perp(v) * d / abs(v), v};}
    double dis(letp &a) const {return abs(v ^ (a - p)) / abs(v);} 
};

struct S {
    P a, b;

    // on endpoints = -1 | out = 0 | in = 1
    int is_on(letp &p) const {
        if (p == a || p == b) return -1;
        return (p - a).ori(p - b) == 0 && ((p - a) | (p - b)) < -eps;
    }

    // inter on endpoints = -1 | not inter = 0 | inter inside = 1
    int is_inter(letl &l) const {
        if (l.ori(a) == 0 || l.ori(b) == 0) return -1;
        return l.ori(a) != l.ori(b);
    }

    // inter on endpoints = -1 | not inter = 0 | inter inside = 1
    int is_inter(lets &s) const {
        if (is_on(s.a) || is_on(s.b) || s.is_on(a) || s.is_on(b)) return -1;
        letl &l{a, b - a}, ls{s.a, s.b - s.a};
        return l.ori(s.a) * l.ori(s.b) == -1 && ls.ori(a) * ls.ori(b) == -1;
    }

    double dis(letp &p) const {
        if (((p - a) | (b - a)) < -eps || ((p - b) | (a - b)) < -eps) 
            return min(abs(a - p), abs(b - p));
        return L{a, b - a}.dis(p);
    }
};

struct Polygon {
    vector<P> p; // counterclockwise
    Polygon(const vector<P> p = {}) : p(p) {}
    size_t nxt(const size_t i) const {return i == p.size() - 1 ? 0 : i + 1;}
    size_t pre(const size_t i) const {return i == 0 ? p.size() - 1 : i - 1;}
    T double_area() const {
        T sum = 0;
        for (size_t i = 0; i < p.size(); ++i) sum += (p[i] ^ p[nxt(i)]);
        return sum;
    }
    double area() const {return double_area() / 2.0;}
    double circ() const {
        long double sum = 0;
        for (size_t i = 0; i < p.size(); ++i) sum += abs(p[i] - p[nxt(i)]);
        return sum;
    }

    // pair<is_on_edge, winding number> , out = [winding number = 0]
    pair<bool,int> winding(letp &a) const {
        int cnt = 0;
        for (size_t i = 0; i < p.size(); ++i) {
            letp u = p[i], v = p[nxt(i)];
            if (z((a - u) ^ (a - v)) && ((a - u) | (a - v)) <= eps) return {true, 0};
            if (z(u.y - v.y)) continue;
            letl uv{u, v - u};
            if (u.y < v.y - eps && uv.ori(a) <= 0) continue;
            if (u.y > v.y + eps && uv.ori(a) >= 0) continue;
            if (u.y < a.y - eps && v.y >= a.y - eps) cnt++;
            if (u.y >= a.y - eps && v.y < a.y - eps) cnt--;
        }
        return {false, cnt};
    }

};

struct C : Polygon {
    C (const vector<P> &p = {}) : Polygon(p) {}
    C operator + (letc &c) const {
        const auto &p = this -> p;
        vector<S> e1(p.size()), e2(c.p.size());
        vector<S> edge(p.size() + c.p.size());
        vector<P> res; res.reserve(p.size() + c.p.size());
        
        const auto cmp = [](lets &u, lets &v) {
            return argcmp()(u.b - u.a, v.b - v.a);
        };

        for (size_t i = 0; i < p.size(); ++i) e1[i] = {p[i], p[this -> nxt(i)]};
        for (size_t i = 0; i < c.p.size(); ++i) e2[i] = {c.p[i], c.p[c.nxt(i)]};
        rotate(e1.begin(), min_element(e1.begin(), e1.end(), cmp), e1.end());
        rotate(e2.begin(), min_element(e2.begin(), e2.end(), cmp), e2.end());
        merge(e1.begin(), e1.end(), e2.begin(), e2.end(), edge.begin(), cmp);

        const auto check = [](const vector<P> &res, letp &u) {
            const auto b1 = res.back(), b2 = *prev(res.end(), 2);
            return (b1 - b2).ori(u - b1) == 0 && ((b1 - b2) | (u - b1)) >= -eps;
        };
        
        auto u = e1[0].a + e2[0].a;
        for (const auto &v : edge) {
            while (res.size() > 1 && check(res, u)) res.pop_back();
            res.push_back(u); u = u + v.b - v.a;
        }
        if (res.size() > 1 && check(res, res[0])) res.pop_back();
        return {res};
    }

    // O(log n) : on = -1 | out = 0 | in = 1
    int is_in(letp &a) const {
        const auto &p = this -> p;
        if (p.size() == 1) return a == p[0] ? -1 : 0;
        if (p.size() == 2) return S{p[0], p[1]}.is_on(a) ? -1 : 0; 
        if (a == p[0]) return -1;
        if ((p[1] - p[0]).ori(a - p[0]) == -1) return 0;
        if ((p.back() - p[0]).ori(a - p[0]) == 1) return 0;
        let cmp = [&](letp &u, letp &v) {return (u - p[0]).ori(v - p[0]) == 1;};
        const size_t i = lower_bound(p.begin() + 1, p.end(), a, cmp) - p.begin();
        if (i == 1) return S{p[0], p[i]}.is_on(a) ? -1 : 0;
        if (i == p.size() - 1 && S{p[0], p[i]}.is_on(a)) return -1;
        if (S{p[i - 1], p[i]}.is_on(a)) return -1;
        return (p[i] - p[i - 1]).ori(a - p[i - 1]) > 0;
    }

    template<typename F> size_t extreme(const F &dir) const {
        let &p = this -> p;
        let check = [&](const size_t i) {return dir(p[i]).ori(p[nxt(i)] - p[i]) >= 0;};
        let dir0 = dir(p[0]); 
        let check0 = check(0);
        if (!check0 && check(p.size() - 1)) return 0;
        const auto cmp = [&](letp &v) {
            const size_t vi = &v - p.data();
            if (vi == 0) return 1;
            let checkv = check(vi);
            let t = dir0.ori(v - p[0]);
            if (vi == 1 && checkv == check0 && dir0.ori(v - p[0]) == 0) return 1;
            return checkv ^ (checkv == check0 && t <= 0);
        };
        return partition_point(p.begin(), p.end(), cmp) - p.begin();
    }

    pair<size_t,size_t> tangent(letp &a) const {
        const size_t i = extreme([&](letp &u){return u - a;});
        const size_t j = extreme([&](letp &u){return a - u;});
        return {i, j};
    }

    pair<size_t,size_t> tangent(letl &a) const {
        const size_t i = extreme([&](...){return a.v;});
        const size_t j = extreme([&](...){return -a.v;});
        return {i, j};
    }

};

C convexHull(vector<P> p) {
    vector<P> st;
    sort(p.begin(), p.end());
    const auto check = [](const vector<P> &st, letp &u) {
        const auto back1 = st.back(), back2 = *prev(st.end(), 2);
        return (back1 - back2).ori(u - back2) <= 0;
    };
    for (letp &u : p) {
        while (st.size() > 1 && check(st, u)) st.pop_back();
        st.push_back(u);
    }
    size_t k=st.size();
    p.pop_back(); reverse(p.begin(),p.end());
    for (letp &u : p) {
        while (st.size() > k && check(st, u)) st.pop_back();
        st.push_back(u);
    }
    st.pop_back();
    return {st};
}

C c;

vector<P> p;

inline void work() {
    p.clear();
    int n = rd(), q = rd(); p.resize(n);
    for (int i = 0; i < n; ++i) {p[i].x = rd(); p[i].y = rd();}
    c = convexHull(p);
    ll s = c.double_area();
    ll dlt = 0;
    for (size_t i = 0; i < c.p.size(); ++i) {
        P cur = c.p[c.nxt(i)] - c.p[i];
        dlt += max(abs(cur.x), abs(cur.y));
    }
    for (int i = 1; i <= q; ++i) {
        ll t = rd();
        ll ans = s + 4 * t * t + 2 * t * dlt;
        printf("%lld", ans / 2);
        puts((ans & 1) ? ".5" : ".0");
    }
}

int main() {
    for (int t = rd(); t; --t) work();
    return 0;
}

详细

Test #1:

score: 100
Accepted
time: 44ms
memory: 6568kb

input:

11
3 3
2 3
4 3
1 1
1
2
3
3 3
4 1
3 4
2 1
2
3
4
10 10
37 76
71 57
66 82
85 85
21 12
94 70
60 6
68 52
2 68
29 53
19
21
46
9
99
65
44
90
50
21
10 10
26 21
77 57
38 96
80 94
5 74
95 53
58 99
50 54
74 25
29 4
54
74
50
51
82
100
15
77
42
64
10 10
14 97
5 89
37 42
36 94
67 68
20 92
42 61
67 77
53 44
99 92
...

output:

11.0
24.0
41.0
27.0
45.0
67.0
10297.0
10971.0
20746.0
7167.0
49737.0
29847.0
19872.0
44022.0
22542.0
10971.0
25391.0
35691.0
23523.0
23984.0
40259.0
51473.0
9908.0
37374.0
19979.0
30341.0
33215.5
41660.5
28085.5
33750.5
17010.5
4032.5
12239.5
22904.5
32684.5
29582.5
45013.5
5764.5
26279.5
9208.5
170...

result:

ok 203046 lines