제출 #147156

#제출 시각아이디문제언어결과실행 시간메모리
147156jh05013Bulldozer (JOI17_bulldozer)C++17
100 / 100
846 ms91432 KiB
#include <bits/stdc++.h>
#define entire(x) begin(x),end(x)
#define dbgv(V) {for(auto x:V)cout<<x<<' ';cout<<endl;}
using namespace std;
typedef long long ll;

const ll INF = 0x3f3f3f3f3f3f3f3f;
struct Segnode{
    ll sum, ans, L, R;

    Segnode(): sum{0}, ans{-INF}, L{-INF}, R{-INF} {}
    void operator=(ll x){
        sum = ans = L = R = x;
    }
    void combine(Segnode A, Segnode B){
        sum = A.sum + B.sum;
        L = max(A.L, A.sum + B.L);
        R = max(B.R, B.sum + A.R);
        ans = max({A.ans, B.ans, A.R+B.L});
    }
};

struct Segtree{    
    int n; vector<Segnode> arr;
    Segtree(int sz): n{1} {
        while(n < sz) n<<=1;
        arr.resize(n*2);
    }
    Segnode &operator[](int i){return arr[i+n];}
    void initialize(){for(int i=n-1; i>=0; i--) arr[i].combine(arr[2*i], arr[2*i+1]);}
    void update(int i){for(i+= n; i>>=1;) arr[i].combine(arr[i<<1], arr[i<<1|1]);}
    Segnode query(int l, int r){
        Segnode resl, resr, ans;
        for(l+= n, r+= n+1; l < r; l/= 2, r/= 2){
            if(l&1) resl.combine(resl, arr[l++]);
            if(r&1) resr.combine(arr[--r], resr);
        }
        ans.combine(resl, resr);
        return ans;
    }
};

struct Point{ll x, y;};
struct Frac{
    ll n, d;
    Frac(){Frac(0,0);}
    Frac(ll a, ll b){
        if(b==0) n=abs(a), d=0;
        else if(b<0) n=-a, d=-b;
        else n=a, d=b;
    }
};
bool operator==(const Frac &A, const Frac &B){
    return A.n*B.d == A.d*B.n;
}
bool operator<(const Frac &A, const Frac &B){
    return A.n*B.d < A.d*B.n;
}

vector<Point> P;
const ll fs = -2000000005;
int main(){
    cin.tie(NULL); ios_base::sync_with_stdio(false);
    
    // IO and special case
    int n; cin>>n;
    P.resize(n);
    vector<ll> score(n);
    for(int i=0; i<n; i++) cin>>P[i].x>>P[i].y>>score[i];
    if (n == 1){cout<<max(0LL,score[0]); return 0;}

    // (Slope, intercept, p1, p2)
    vector<tuple<Frac, Frac, int, int>> slope;
    for(int i=0; i<n; i++) for(int j=i+1; j<n; j++){
        Frac a(P[i].y-P[j].y, P[i].x-P[j].x), b;
        if(a.d == 0) b = Frac(P[i].x, 1);
        else b = Frac(P[i].y*a.d - P[i].x*a.n, a.d);
        slope.push_back(make_tuple(a, b, i, j));
    }
    sort(entire(slope));
    slope.push_back(slope[0]); // sentinel

    // Points sorted by y-intercept
    vector<int> C(n);
    iota(entire(C), 0);
    sort(entire(C), [](const int &a, const int &b)
        {return P[a].y-P[a].x*fs < P[b].y-P[b].x*fs;});
    Segtree ST(n);
    for(int i=0; i<n; i++) ST[i] = score[C[i]];
    ST.initialize();
    ll ans = max(0LL, ST.query(0,n-1).ans);

    // Reverse map
    vector<int> rev(n), colinear;
    for(int i=0; i<n; i++) rev[C[i]] = i;

    // Scan
    size_t ss = slope.size()-1; // Excluding sentinel
    for(size_t si=0; si<ss; si++){
        Frac a1,b1; int i1,j1; tie(a1,b1,i1,j1) = slope[si];
        Frac a2,b2; int i2,j2; tie(a2,b2,i2,j2) = slope[si+1];
        colinear.push_back(rev[i1]);
        colinear.push_back(rev[j1]);
        if(si != ss-1 && a1 == a2 && b1 == b2) continue;
        // Invert
        int l = *min_element(entire(colinear));
        int r = *max_element(entire(colinear));
        while(l < r){
            int pl = C[l], pr = C[r];
            ST[l] = score[pr], ST.update(l);
            ST[r] = score[pl], ST.update(r);
            rev[pl] = r, rev[pr] = l;
            swap(C[l], C[r]);
            l++, r--;
        }
        colinear.clear();
        if(si != ss-1 && a1 == a2) continue;
        ll V = ST.query(0,n-1).ans;
        ans = max(ans, V);
    }
    cout<<ans;
}
#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...