Submission #1198502

#TimeUsernameProblemLanguageResultExecution timeMemory
1198502Zero_OPBulldozer (JOI17_bulldozer)C++20
100 / 100
756 ms33680 KiB
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

#define dbg(x) "[" #x " = " << (x) << "]"

struct point{
      int x, y, c;
      bool operator < (const point& o) const {
            return make_pair(y, x) < make_pair(o.y, o.x);
      }
};

struct Node{
      ll pref, suff, best, sum;
      Node(ll s) : pref(s), suff(s), best(s), sum(s) {}
      Node(ll a, ll b, ll c, ll d) : pref(a), suff(b), best(c), sum(d) {}

      friend Node operator + (const Node& a, const Node& b){
            return Node(max(a.pref, a.sum + b.pref), max(b.suff, b.sum + a.suff), max({a.best, b.best, a.suff + b.pref}), a.sum + b.sum);
      }
};

struct SegmentTree{
      vector<Node> st;
      SegmentTree(int n) : st(n * 4, Node(0)) {}

      void update(int id, int l, int r, int pos, int val){
            if(l == r) st[id] = Node(val);
            else{
                  int mid = l + r >> 1;
                  if(pos <= mid) update(id << 1, l, mid, pos, val);
                  else update(id << 1 | 1, mid + 1, r, pos, val);
                  st[id] = st[id << 1] + st[id << 1 | 1];
            }
      }

      ll query(){
            return st[1].best;
      }
};

int sign(int x){
      return (x < 0 ? -1 : (x > 0 ? +1 : 0));
}

bool cmp(int a1, int b1, int a2, int b2){
      //vector u(a1, b1) and v(a2, b2)
//      int s1 = sign(a1), s2 = sign(a2);
//      if(s1 != s2) return s1 < s2;
//      return (s1 == +1 ? 1LL * a1 * b2 < 1LL * a2 * b1 : 1LL * a1 * b2 > 1LL * a2 * b1);
      return 1LL * a1 * b2 < 1LL * a2 * b1;
}

struct line{
      int x, y, l, r;
      line(int x, int y, int l, int r) : x(x), y(y), l(l), r(r) {}

      bool operator < (const line& o) const {
            if(x == o.x && y == o.y) return make_pair(l, r) < make_pair(o.l, o.r);
            return cmp(x, y, o.x, o.y);
      }
};

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

#ifdef LOCAL
      freopen("task.inp", "r", stdin);
      freopen("task.out", "w", stdout);
#endif // LOCAL

      int N;
      cin >> N;
      vector<point> p(N);
      for(int i = 0; i < N; ++i) cin >> p[i].x >> p[i].y >> p[i].c;

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

      SegmentTree T(N);
      for(int i = 0; i < N; ++i) T.update(1, 0, N-1, i, p[i].c);
      ll ans = max(0ll, T.query());

      vector<line> v;
      for(int i = 0; i < N; ++i){
            for(int j = i+1; j < N; ++j){
                  ll a = p[i].x - p[j].x;
                  ll b = p[i].y - p[j].y;
                  ll d = __gcd(abs(a), abs(b));
                  a /= d; b /= d;
                  if(abs(a) == 1 && b == 0) continue;

                  if(b < 0) a = -a, b = -b;
                  v.emplace_back(line(a, b, i, j));
            }
      }

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

      vector<int> idx(N);
      iota(idx.begin(), idx.end(), 0);

      auto output_idx = [&](){
            vector<int> pos(N);
            for(int i = 0; i < N; ++i) pos[idx[i]] = i;
            for(int i = 0; i < N; ++i) cout << p[pos[i]].c << ' '; cout << '\n';
//            for(int i = 0; i < N; ++i) cout << st<< ' '; cout << '\n';
            cout << "Checking \n\n";
      };


//      output_idx();
//      for(int i = 0; i < (int)v.size(); ++i) cout << '(' << v[i].x << ' ' << v[i].y << ") : " << v[i].l << ' ' << v[i].r << '\n';
//      cout << dbg(ans) << '\n';
//      return 0;
      for(int i = 0; i < (int)v.size(); ++i){
            int a = v[i].l, b = v[i].r;
            swap(idx[a], idx[b]);
            T.update(1, 0, N-1, idx[a], p[a].c);
            T.update(1, 0, N-1, idx[b], p[b].c);
//            cout << dbg(idx[a]) << dbg(idx[b]) << '\n';
            while(i+1 < (int)v.size() && v[i].x == v[i+1].x && v[i].y == v[i+1].y){
                  ++i;
                  int a = v[i].l, b = v[i].r;
                  swap(idx[a], idx[b]);
                  T.update(1, 0, N-1, idx[a], p[a].c);
                  T.update(1, 0, N-1, idx[b], p[b].c);
//                  cout << dbg(idx[a]) << dbg(idx[b]) << "!!\n";
            }

//            cout << dbg(ans) << '\n';
            ans = max(ans, T.query());
//            output_idx();
      }
      cout << ans << '\n';

      return 0;
}

/*

a, b, c -> c, b, a

(a, b), (a, c), (b, c)
a, b, c -> b, a, c -> b, c, a -> b, c, a

a, b, c, d, -> d, c, b, a
(a, b), (a, c), (a, d), (b, c), (b, d), (c, d)

a, b, c, d
b, a, c, d
b, c, a, d
b, c, d, a
c, b, d, a


*/
#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...