Submission #161722

#TimeUsernameProblemLanguageResultExecution timeMemory
161722darkkcyanBulldozer (JOI17_bulldozer)C++14
25 / 100
2047 ms116312 KiB
#include <bits/stdc++.h>
using namespace std;
using namespace std::placeholders;

#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 sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define clog if (0) 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);
// }

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 (!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 = sgn(lhs.a * rhs.b - lhs.b * rhs.a);
        if (cross == 0) return lhs.c < rhs.c;
        return cross > 0;
    }
};

int n;
spot a[maxn];

int main(void) {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n;
    rep(i, n) 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;

    rep(i, n) {
        clog << i << ":" << a[i].x << ' ' << a[i].y << ' ' << a[i].cost << endl;
    }

    map<line, vector<spot*>, cmp_line> group;
    rep(i, n) {
        for (int f = i + 1; f < n; ++f) {
            line ln = line::through_points(a[i], a[f]);
            group[ln].push_back(a + i);
            group[ln].push_back(a + f);
        }
    }

    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();

    vector<vector<spot*>> to_be_processed;
    auto process = [&]() {
        for (auto& i: to_be_processed) {
            sort(i.begin(), i.end(), [](spot* u, spot* v) { return u->pos < v->pos; });
            i.resize(unique(i.begin(), i.end()) - i.begin());
            rep1(f, len(i) - 1) {
                tree.inc(i[f]->pos, -i[f]->cost);
                tree.inc(i[0]->pos, i[f]->cost);
            }
        }
        upd_ans();
        for (auto& i: to_be_processed) {
            int first_pos = i[0]->pos;
            rep(f, len(i) - 1) {
                tree.inc(first_pos, -i[f]->cost);
                if (f < len(i) - f - 1) swap(i[f]->pos, i[len(i) - f - 1]->pos);
                tree.inc(i[f]->pos, i[f]->cost);
            }
        }
        upd_ans();
    };

    line cur_line(1, 0, 0);
    for (auto& [ln, points]: group) {
        if (cur_line.a != ln.a or cur_line.b != ln.b) {
            clog << "=== process" << endl;
            process();
            to_be_processed.clear();
            cur_line = ln;
        }
        to_be_processed.push_back(move(points));
        clog << "line : " << -ln.b << ' ' << ln.a << endl;
    }
    process();
    cout << ans;
    return 0;
}

Compilation message (stderr)

bulldozer.cpp: In function 'int main()':
bulldozer.cpp:186:16: warning: decomposition declaration only available with -std=c++1z or -std=gnu++1z
     for (auto& [ln, points]: group) {
                ^
#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...