Submission #161737

#TimeUsernameProblemLanguageResultExecution timeMemory
161737darkkcyanBulldozer (JOI17_bulldozer)C++14
25 / 100
2055 ms82644 KiB
#include <bits/stdc++.h> using namespace std; using namespace std::placeholders; #define debug 0 #define llong long long #define xx first #define yy second #define len(x) ((int)x.size()) #define rep(i,n) for (int i = -1; ++ i < n; ) #define rep1(i,n) for (int i = 0; i ++ < n; ) #define all(x) x.begin(), x.end() #define clog if (debug) cerr // #define rand __rand // mt19937 rng(chrono::system_clock::now().time_since_epoch().count()); // or mt19937_64 // template<class T = int> T rand(T range = numeric_limits<T>::max()) { // return (T)(rng() % range); // } template<class Num> int sign(Num num) { return num < 0 ? -1 : num > 0; } struct itnode { llong max_sum_subarr, max_left_sum, max_right_sum, sum; itnode *lchild, *rchild; int l, r; // [l; r) itnode(int l_, int r_, function<llong(int)> getitem) : lchild(0), rchild(0), l(l_), r(r_) { if (l + 1 == r) { assign(getitem(l)); } if (l + 1 >= r) return ; int mid = (l + r) / 2; lchild = new itnode(l, mid, getitem); rchild = new itnode(mid, r, getitem); merge(); } ~itnode() { if (!lchild) return ; delete lchild; delete rchild; } void assign(llong val) { sum = val; max_sum_subarr = sum; max_right_sum = max_left_sum = max(sum, 0ll); } void merge() { if (!lchild || !rchild) return ; sum = lchild->sum + rchild->sum; max_sum_subarr = max({lchild->max_sum_subarr, rchild->max_sum_subarr, lchild->max_right_sum + rchild->max_left_sum}); max_left_sum = max(lchild->max_left_sum, lchild->sum + rchild->max_left_sum); max_right_sum = max(rchild->max_right_sum, rchild->sum + lchild->max_right_sum); } void inc(int pos, llong val) { if (pos < l or pos >= r) return ; if (l + 1 == r) { assign(sum + val); return ; } lchild->inc(pos, val); rchild->inc(pos, val); merge(); } void dolog() { if (!debug) return ; if (!lchild) { // clog << setw(4) << sum << ' '; } else { lchild->dolog(); rchild->dolog(); } } }; struct line { llong a, b, c; // ax + by + c = 0 line(llong a_ = 0, llong b_ = 0, llong c_ = 0) : a(a_), b(b_), c(c_) {} line& norm() { llong g = __gcd(a, b); g = __gcd(g, c); a /= g; b /= g; c /= g; // the normal will point almost the same way as Oy // also the line a == b == 0 does not "really" exist, no need to handle it. if (b < 0 || (b == 0 and a < 0)) { a = -a; b = -b; c = -c; } return *this; } template<class Point> static line through_points(Point const& u, Point const& v) { return line( u.y - v.y, - u.x + v.x, u.x * v.y - u.y * v.x ).norm(); } }; bool operator == (const line& lhs, const line& rhs) { return lhs.a == rhs.a and lhs.b == rhs.b and lhs.c == rhs.c; } #define maxn 2020 struct spot { llong x, y, cost; int pos; spot(llong x_ = 0, llong y_ = 0, llong v = 0) : x(x_), y(y_), cost(v), pos(0) {} }; struct cmp_line { bool operator()(const line& lhs, const line& rhs) const { int cross = sign(lhs.a * rhs.b - lhs.b * rhs.a); if (cross == 0) return lhs.c < rhs.c; return cross > 0; } }; int n; spot* a[maxn]; // for the sake of keeping things in places, I used pointer. int main(void) { auto t1 = std::chrono::high_resolution_clock::now(); ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n; rep(i, n) { a[i] = new spot(); cin >> a[i]->x >> a[i]->y >> a[i]->cost; } sort(a, a + n, [](const spot* u, const spot* v) { return (u->x == v->x) ? u->y > v->y : u->x < v->x; }); rep(i, n) a[i]->pos = i; clog << "ok boomer" << endl; vector<tuple<line, spot*, spot*>> groups; rep(i, n) { for (int f = i + 1; f < n; ++f) { line ln = line::through_points(*a[i], *a[f]); groups.emplace_back(ln, a[i], a[f]); } } sort(groups.begin(), groups.end(), [](auto const& u, auto const& v) { return cmp_line()(get<0>(u), get<0>(v)); }); clog << "ok boomer" << endl; itnode tree(0, n, [](int u) { return a[u]->cost; }); llong ans = 0; auto upd_ans = [&]() { // clog << setw(3) << ans << ' ' << setw(3) << tree.max_sum_subarr << ": "; // tree.dolog(); clog << endl; ans = max(ans, tree.max_sum_subarr); }; upd_ans(); clog << "ok boomer" << endl; vector<tuple<llong, int, int>> ranges; auto process = [&]() { for (auto [c, min_pos, max_pos]: ranges) { llong sum = 0; for (int i = min_pos + 1; i <= max_pos; ++i) { tree.inc(i, -a[i]->cost); sum += a[i]->cost; } tree.inc(min_pos, sum); } upd_ans(); for (auto [c, min_pos, max_pos]: ranges) { for (int l = min_pos, r = max_pos; l < r; ++l, --r) { swap(a[l]->pos, a[r]->pos); swap(a[l], a[r]); } llong sum = 0; for (int i = min_pos + 1; i <= max_pos; ++i) { sum += a[i]->cost; tree.inc(i, a[i]->cost); } tree.inc(min_pos, -sum); } upd_ans(); }; line cur_line(1, 0, 0); for (auto& [ln, p1, p2]: groups) { if (cur_line.a != ln.a or cur_line.b != ln.b) { // clog << "=== process" << endl; process(); ranges.clear(); } if (ranges.empty() or cur_line.c != ln.c) { ranges.emplace_back(ln.c, n, 0); } for (auto& i: {p1, p2}) { get<1>(ranges.back()) = min(get<1>(ranges.back()), i->pos); get<2>(ranges.back()) = max(get<2>(ranges.back()), i->pos); } cur_line = ln; // clog << "line : " << -ln.b << ' ' << ln.a << endl; } process(); cout << ans; auto t2 = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count(); clog << duration ; return 0; }

Compilation message (stderr)

bulldozer.cpp: In lambda function:
bulldozer.cpp:173:19: warning: decomposition declaration only available with -std=c++1z or -std=gnu++1z
         for (auto [c, min_pos, max_pos]: ranges) {
                   ^
bulldozer.cpp:173:39: warning: unused variable 'c' [-Wunused-variable]
         for (auto [c, min_pos, max_pos]: ranges) {
                                       ^
bulldozer.cpp:182:19: warning: decomposition declaration only available with -std=c++1z or -std=gnu++1z
         for (auto [c, min_pos, max_pos]: ranges) {
                   ^
bulldozer.cpp:182:39: warning: unused variable 'c' [-Wunused-variable]
         for (auto [c, min_pos, max_pos]: ranges) {
                                       ^
bulldozer.cpp: In function 'int main()':
bulldozer.cpp:199:16: warning: decomposition declaration only available with -std=c++1z or -std=gnu++1z
     for (auto& [ln, p1, p2]: groups) {
                ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...