Submission #390288

#TimeUsernameProblemLanguageResultExecution timeMemory
390288dooweyIOI Fever (JOI21_fever)C++14
100 / 100
3308 ms178176 KiB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pii;

#define fi first
#define se second
#define mp make_pair
#define fastIO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

const int N = (int)1e5 + 100;
ll H[N], W[N];
int dir[4][2] = {{0,+1},{0,-1},{+1,0},{-1,0}};
int n;

int sol = 0;

struct E{
    ll val;
    ll sec;
    int idx;
    bool operator<(const E &e) const {
        if(val == e.val)
            return sec < e.sec;
        return val < e.val;
    }
};

vector<E> vv[4][4];

struct node{
    pii low_val;
    pii sol;
    ll lazy;
};

struct segment_tree{
    vector<ll> vls;
    vector<node> pap;
    int m;
    void build(int node, int cl, int cr){
        pap[node].lazy = -(ll)1e18;
        if(cl == cr){
            pap[node].low_val = mp(vls[cl], cl);
            pap[node].sol = mp((ll)1e18, cl);
            return;
        }
        int mid = (cl + cr) / 2;
        build(node * 2, cl, mid);
        build(node * 2 + 1, mid + 1, cr);
        pap[node].low_val = min(pap[node*2].low_val, pap[node*2+1].low_val);
        pap[node].sol = min(pap[node*2].sol, pap[node*2+1].sol);
    }
    void init(vector<E> sha){
        vls.clear();
        pap.clear();
        m = sha.size();
        if(m == 0) return;
        pap.resize(4 * m + 16);
        for(int i = 0 ; i < m ; i ++ ){
            vls.push_back(sha[i].sec);
        }
        build(1, 0, m - 1);
    }
    void push(int node, int cl, int cr){
        pap[node].sol = min(pap[node].sol, mp(pap[node].low_val.fi - pap[node].lazy,pap[node].low_val.se));
        if(cl != cr){
            pap[node*2].lazy = max(pap[node*2].lazy, pap[node].lazy);
            pap[node*2+1].lazy = max(pap[node*2+1].lazy, pap[node].lazy);
        }
    }
    void update(int node, int cl, int cr, int tl, int tr, ll vv){
        push(node, cl, cr);
        if(cr < tl || cl > tr){
            return;
        }
        if(cl >= tl && cr <= tr){
            pap[node].lazy = max(pap[node].lazy, vv);
            push(node, cl, cr);
            return;
        }
        int mid = (cl + cr) / 2;
        update(node * 2, cl, mid, tl, tr, vv);
        update(node * 2 + 1, mid + 1, cr, tl, tr, vv);
        pap[node].sol = min(pap[node * 2].sol, pap[node * 2 + 1].sol);
    }
    void clean(int node, int cl, int cr, int id){
        push(node, cl, cr);
        if(cl == cr){
            pap[node].low_val = mp((ll)1e18, id);
            pap[node].sol = mp((ll)1e18, id);
            return;
        }
        int mid = (cl + cr) / 2;
        if(mid >= id)
            clean(node * 2, cl, mid, id);
        else
            clean(node * 2 + 1, mid + 1, cr, id);
        pap[node].low_val = min(pap[node*2].low_val, pap[node*2+1].low_val);
        pap[node].sol = min(pap[node * 2].sol, pap[node * 2 + 1].sol);
        pap[node].sol = min(pap[node].sol, mp(pap[node].low_val.fi - pap[node].lazy, pap[node].low_val.se));
    }
};

segment_tree opt[4][4];
int go[N];
ll low[N];

int solve(){
    go[0] = 0;
    for(int i = 2; i <= n; i ++ ){
        if(abs(H[i]) == abs(W[i])){
            if(W[i] < 0) go[i] = 0;
            else {
                if(H[i] > 0)
                    go[i] = 3;
                else
                    go[i] = 2;
            }
        }
        else{
            if(abs(H[i]) > abs(W[i])){
                if(H[i] > 0)
                    go[i] = 3;
                else
                    go[i] = 2;
            }
            else{
                if(W[i] > 0){
                    go[i] = 1;
                }
                else{
                    go[i] = 0;
                }
            }
        }
        low[i]=(ll)1e18;
    }
    low[1]=0;
    for(int p = 0 ; p < 4; p ++ ){
        for(int q = 0; q < 4; q ++ ){
            vv[p][q].clear();
        }
    }
    E cur;
    ll AH, AW;
    for(int p = 0 ; p < 4; p ++ ){
        for(int i = 1; i <= n; i ++ ){
            if(go[i] != p){
                AH = dir[p][0] - dir[go[i]][0];
                AW = dir[p][1] - dir[go[i]][1];
                cur.val = AW * 1ll * H[i] - AH * 1ll * W[i];
                if(AH != 0) cur.sec = H[i] / AH;
                else cur.sec = W[i] / AW;
                cur.idx = i;
                vv[p][go[i]].push_back(cur);
            }
        }
    }
    for(int p = 0 ; p < 4; p ++ ){
        for(int q = 0; q < 4; q ++ ){
            sort(vv[p][q].begin(), vv[p][q].end());
            opt[p][q].init(vv[p][q]);
        }
    }
    int cnt = 0;
    int id = -1;
    ll nw;
    int cid;
    ll add;
    int lf, rf;
    int nex;
    int iq;
    while(1){
        if(cnt == 0){
            id = 1;
            low[id] = 0;
        }
        else{
            nw = (ll)2e18;
            cid = -1;
            for(int p = 0;  p < 4; p ++ ){
                for(int q = 0; q < 4; q ++ ){
                    if(p == q || opt[p][q].m == 0) continue;
                    if(opt[p][q].pap[1].sol.fi < nw){
                        nw = opt[p][q].pap[1].sol.fi;
                        cid = vv[p][q][opt[p][q].pap[1].sol.se].idx;
                    }
                }
            }
            if(nw > (ll)1e14) break;
            id = cid;
            low[id] = nw;
        }
        cnt ++ ;
        for(int p = 0 ; p < 4; p ++ ){
            if(p == go[id]) continue;
            AH = dir[p][0] - dir[go[id]][0];
            AW = dir[p][1] - dir[go[id]][1];
            cur.val = AW * H[id] - AH * W[id];
            if(AH != 0) cur.sec = H[id] / AH;
            else cur.sec = W[id] / AW;
            cur.idx = -1;
            iq = lower_bound(vv[p][go[id]].begin(), vv[p][go[id]].end(), cur) - vv[p][go[id]].begin();
            opt[p][go[id]].clean(1, 0, opt[p][go[id]].m - 1, iq);
        }
        for(int nx = 0; nx < 4; nx ++ ){
            if(nx == go[id] || vv[go[id]][nx].empty()) continue;
            AH = dir[go[id]][0] - dir[nx][0];
            AW = dir[go[id]][1] - dir[nx][1];
            cur.val = AW * H[id] - AH * W[id];
            cur.sec = low[id];
            if(AH != 0) add = H[id] / AH;
            else add = W[id] / AW;
            cur.sec += add;
            lf = lower_bound(vv[go[id]][nx].begin(), vv[go[id]][nx].end(), cur) - vv[go[id]][nx].begin();
            if(lf < vv[go[id]][nx].size() && vv[go[id]][nx][lf].val == cur.val){
                rf = lf;
                for(int lg = 17; lg >= 0 ; lg -- ){
                    nex = rf + (1 << lg);
                    if(nex < vv[go[id]][nx].size() && vv[go[id]][nx][nex].val == cur.val){
                        rf = nex;
                    }
                }
                opt[go[id]][nx].update(1, 0, opt[go[id]][nx].m - 1, lf, rf, add);
            }
        }
    }
    return cnt;
}

int main(){
    fastIO;
    cin >> n;
    for(int i = 1; i <= n; i ++ ){
        cin >> H[i] >> W[i];
        H[i] *= 2ll;
        W[i] *= 2ll;
        if(i > 1){
            H[i] -= H[1];
            W[i] -= W[1];
        }
    }
    H[1] = 0;
    W[1] = 0;
    int sol = solve();
    for(int i = 1; i <= n; i ++ ){
        W[i] = -W[i];
    }

    sol = max(sol, solve());
    for(int i = 1; i <= n; i ++ ){
        swap(H[i], W[i]);
    }
    sol = max(sol, solve());
    for(int i = 1; i <= n; i ++ ){
        W[i] = -W[i];
    }
    sol = max(sol, solve());
    cout << sol << "\n";
    return 0;
}

Compilation message (stderr)

fever.cpp: In function 'int solve()':
fever.cpp:220:19: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<E>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  220 |             if(lf < vv[go[id]][nx].size() && vv[go[id]][nx][lf].val == cur.val){
      |                ~~~^~~~~~~~~~~~~~~~~~~~~~~
fever.cpp:224:28: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<E>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  224 |                     if(nex < vv[go[id]][nx].size() && vv[go[id]][nx][nex].val == cur.val){
      |                        ~~~~^~~~~~~~~~~~~~~~~~~~~~~
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...