답안 #1020338

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1020338 2024-07-12T00:10:25 Z esomer Colouring a rectangle (eJOI19_colouring) C++17
100 / 100
627 ms 53728 KB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll INF = 1e18;

struct segTree{
    vector<ll> v, pre, upd;
    int sz;
    void init(int n){
        sz = 1;
        while(sz < n) sz *= 2;
        v.assign(2 * sz, 4*INF);
        upd.assign(2 * sz, 0);
        pre.assign(2 * sz, 4*INF);
    }
    void buildPre(vector<ll>& pr, int x, int lx, int rx){
        if(rx - lx == 1){
            if(lx >= (int)pr.size()){
                return;
            }
            pre[x] = -pr[lx] + INF;
            v[x] = INF;
            return;
        }
        int m = (lx + rx) / 2;
        buildPre(pr, 2 * x + 1, lx, m);
        buildPre(pr, 2 * x + 2, m, rx);
        v[x] = min(v[2 * x + 1], v[2 * x + 2]);
        pre[x] = min(pre[2 * x + 1], pre[2 * x + 2]);
    }
    void buildPre(vector<ll>& pr){
        buildPre(pr, 0, 0, sz);
    }
    void set(int l, int r, ll val, int x, int lx, int rx){
        if(lx >= l && rx <= r){
            upd[x] += val;
            v[x] += val;
            pre[x] += val;
            return;
        }else if(lx >= r || rx <= l) return;
        int m = (lx + rx) / 2;
        set(l, r, val, 2 * x + 1, lx, m);
        set(l, r, val, 2 * x + 2, m, rx);
        v[x] = min(v[2 * x + 1], v[2 * x + 2]) + upd[x];
        pre[x] = min(pre[2 * x + 1], pre[2 * x + 2]) + upd[x];
    }
    void set(int l, int r, ll val){
        set(l, r, val, 0, 0, sz);
    }
    ll calc(int l, int r, int x, int lx, int rx){
        if(lx >= l && rx <= r) return v[x];
        else if(lx >= r || rx <= l) return 2*INF;
        int m = (lx + rx) / 2;
        ll c1 = calc(l, r, 2 * x + 1, lx, m);
        ll c2 = calc(l, r, 2 * x + 2, m, rx);
        return min(c1, c2) + upd[x];
    }
    ll calc(int l, int r){
        return calc(l, r, 0, 0, sz);
    }
    ll calcPre(int l, int r, int x, int lx, int rx){
        if(lx >= l && rx <= r) return pre[x];
        else if(lx >= r || rx <= l) return 2*INF;
        int m = (lx + rx) / 2;
        ll c1 = calcPre(l, r, 2 * x + 1, lx, m);
        ll c2 = calcPre(l, r, 2 * x + 2, m, rx);
        return min(c1, c2) + upd[x];
    }
    ll calcPre(int l, int r){
        return calcPre(l, r, 0, 0, sz);
    }
};

ll getSum(int l, int r, vector<ll>& pre){
    if(l > r) return 0;
    if(l > 0) return pre[r] - pre[l-1];
    else return pre[r];
}

ll solve(int n, int m, vector<int>& down, vector<int>& up){
    // cout << "Down:\n";
    // for(int x : down) cout << x << " "; 
    // cout << "\n";
    // cout << "Up:\n";
    // for(int x : up) cout << x << " "; 
    // cout << "\n";
    vector<tuple<int, int, int>> inv;
    ll sum = 0;
    for(int i = m-1; i >= 0; i--){
        //Itero sobre els downs de la primera FILA, i m'agafo els rangs d'ups que comprenen.
        int s1 = m-i-1;
        int s2 = m-i-1 + (m-1 - (m-1-i)) * 2;
        if(s2 > n+m-2){
            //I don't end at the right column, I end at the bottom line.
            //Therefore, I go from (0, m-i-1) to (n-1, k), and the difference
            //is conserved, so -(m-i-1) = n-1-k -> k = n-1 + m-i-1.
            int k = n-1 + m-i-1;
            //From k, I want to know to which cell of the form (0, x) I belong,
            //and as the sum is preserved, x = n-1 + k.
            s2 = n-1+k;
        }
        s2 = min(s2, n+m-2);
        if(s1 > s2){
            //No hi ha cap rang, estic a alguna cantonada.
            // cout << "iSum "<< i << "\n";
            sum += down[i];
        }else{
            // cout << "i " << i << " s1 " << s1 << " s2 " << s2 << "\n";
            inv.push_back({s1, s2, down[i]});
        }
    }
    for(int i = n+m-2; i >= m; i--){
        //Itero sobre els downs de la primera COLUMNA, i m'agafo els rangs d'ups que comprenen.
        
        //Quan faig up, es conserva la suma. Per tant, jo vull veure a quina cel·la de la forma
        //(0, x) correspon (y, 0). -> x = y.
        int col1 = i-m+1; //Perquè la row és i-m+1.
        
        //Quan faig up, es conserva la suma. Per tant, jo vull veure a quina cel·la de la forma
        //(0, x) correspon (n-1, y). -> x = y+n-1.
        int y = n+m-2-i;
        int col2 = y+n-1;
        if(y >= m){
            //The cell (n-1, y) doesn't exist. Therefore, I want to find the cell
            //(0, x) with (k, m-1) -> x = m-1 + k.
            //Com quan baixo, la diferència es manté, i vaig de (i-m+1, 0) a (k, m-1),
            //tinc que i-m+1 = k-(m-1) -> k = i.
            col2 = m-1 + i;
        }
        col2 = min(col2, n+m-2);
        if(col1 > col2){
            // cout << "iSum "<< i << "\n";
            sum += down[i];
        }else{
            // cout << "i " << i << " col1 " << col1 << " col2 " << col2 << "\n";
            inv.push_back({col1, col2, down[i]});
        }
    }
    sort(inv.begin(), inv.end());
    segTree st; st.init(n+m);
    vector<ll> pre(n+m);
    pre[0] = 0;
    for(int i = 1; i < n+m; i++) pre[i] = pre[i-1] + up[i-1];
    st.buildPre(pre);
    st.set(0, 1, -INF);
    // cout << "sum " << sum << "\n";
    for(auto [l, r, cost] : inv){
        l++; r++; //I have it 1-indexed.
        /*
        El segment tree es guarda st[i] = el mínim cost si he comprat fins a i (em dona igual des d'on, perquè si he comprat
        és per algún rang anterior i ordeno per l, per tant he d'haver comprat des d'una j < l fins a i, i per tant tinc
        des de l fins a i ja comprats, i només he de comprar de i fins a r).
        El faig 1-indexed per considerar la possibilitat de no haver comprat cap.
        */


        //Segona transició, pago tots els ups. Puc o bé no pagar res, si ja he comprat fins a >= r, o bé pagar
        //prefix[r] - prefix[i] + st[i] per l <= i < r o bé st[i] + prefix[r] - prefix[l-1] per i < l. 
        //Per els que no pago res, els deixo igual, només he d'actualitzar st[r].
        ll mn = min(pre[r] + st.calcPre(l, r), st.calc(0, l) + getSum(l, r, pre));
        ll curr = st.calc(r, r + 1);
        if(curr > mn){
            st.set(r, r+1, mn-curr);
        }

        //Primera transició, simplement pago el preu del down, no compro res més, per tant tots es queden igual i els hi
        //sumo el preu del down.
        st.set(0, r, cost); //Els que ja són >= r no he de sumar res, es queden igual.
        
        // cout << "l " << l << " r " << r << " cost "<< cost << "\n";
        // for(int i = 0; i < n+m; i++){
        //     cout << "i " << i << " st "<< st.calc(i, i+1) << "\n";
        // }
    }
    // cout << "v[0] " << st.v[0] << " total " << st.v[0] + sum << "\n";
    return st.v[0] + sum;
}

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

    /*
    Detall que no havia considerat. Realment, quan deixo de posar una down, i omplo amb ups, no estic
    omplint totes les caselles, només les de mateixa paritat, és una mica liada. Però, com les diagonals
    només cobreixen caselles de mateixa paritat, realment no és un problema, perquè vol dir que colorejar
    les caselles parelles i imparelles són dos problemes independents i puc fer el que tenia dos cops.*/

    int n, m; cin >> n >> m;
    vector<int> down(n+m-1);
    for(auto &i : down) cin >> i;
    vector<int> up(n+m-1);
    for(auto &i : up) cin >> i;
    vector<int> downOdd(n+m-1, 0), downEven(n+m-1, 0);
    int odd = (m-1)%2;;
    for(int i = 0; i < n + m - 1; i++){
        if(odd) downOdd[i] = down[i];
        else downEven[i] = down[i];
        odd ^= 1;
    }
    vector<int> upOdd(n+m-1, 0), upEven(n+m-1, 0);
    for(int i = 0; i < n + m - 1; i++){
        if(i%2) upOdd[i] = up[i];
        else upEven[i] = up[i];
    }
    ll ans = solve(n, m, downOdd, upOdd) + solve(n, m, downEven, upEven);
    cout << ans << "\n";
}
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 344 KB Output is correct
2 Correct 1 ms 344 KB Output is correct
3 Correct 0 ms 348 KB Output is correct
4 Correct 1 ms 420 KB Output is correct
5 Correct 0 ms 348 KB Output is correct
6 Correct 0 ms 344 KB Output is correct
7 Correct 0 ms 348 KB Output is correct
8 Correct 0 ms 348 KB Output is correct
9 Correct 0 ms 348 KB Output is correct
10 Correct 0 ms 344 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 344 KB Output is correct
2 Correct 1 ms 344 KB Output is correct
3 Correct 0 ms 348 KB Output is correct
4 Correct 1 ms 420 KB Output is correct
5 Correct 0 ms 348 KB Output is correct
6 Correct 0 ms 344 KB Output is correct
7 Correct 0 ms 348 KB Output is correct
8 Correct 0 ms 348 KB Output is correct
9 Correct 0 ms 348 KB Output is correct
10 Correct 0 ms 344 KB Output is correct
11 Correct 0 ms 344 KB Output is correct
12 Correct 0 ms 348 KB Output is correct
13 Correct 0 ms 348 KB Output is correct
14 Correct 0 ms 348 KB Output is correct
15 Correct 0 ms 348 KB Output is correct
16 Correct 1 ms 344 KB Output is correct
17 Correct 0 ms 348 KB Output is correct
18 Correct 0 ms 348 KB Output is correct
19 Correct 1 ms 348 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 344 KB Output is correct
2 Correct 1 ms 344 KB Output is correct
3 Correct 0 ms 348 KB Output is correct
4 Correct 1 ms 420 KB Output is correct
5 Correct 0 ms 348 KB Output is correct
6 Correct 0 ms 344 KB Output is correct
7 Correct 0 ms 348 KB Output is correct
8 Correct 0 ms 348 KB Output is correct
9 Correct 0 ms 348 KB Output is correct
10 Correct 0 ms 344 KB Output is correct
11 Correct 0 ms 344 KB Output is correct
12 Correct 0 ms 348 KB Output is correct
13 Correct 0 ms 348 KB Output is correct
14 Correct 0 ms 348 KB Output is correct
15 Correct 0 ms 348 KB Output is correct
16 Correct 1 ms 344 KB Output is correct
17 Correct 0 ms 348 KB Output is correct
18 Correct 0 ms 348 KB Output is correct
19 Correct 1 ms 348 KB Output is correct
20 Correct 0 ms 348 KB Output is correct
21 Correct 0 ms 348 KB Output is correct
22 Correct 0 ms 348 KB Output is correct
23 Correct 0 ms 348 KB Output is correct
24 Correct 0 ms 348 KB Output is correct
25 Correct 0 ms 348 KB Output is correct
26 Correct 1 ms 348 KB Output is correct
27 Correct 0 ms 412 KB Output is correct
28 Correct 0 ms 348 KB Output is correct
29 Correct 0 ms 348 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 344 KB Output is correct
2 Correct 1 ms 344 KB Output is correct
3 Correct 0 ms 348 KB Output is correct
4 Correct 1 ms 420 KB Output is correct
5 Correct 0 ms 348 KB Output is correct
6 Correct 0 ms 344 KB Output is correct
7 Correct 0 ms 348 KB Output is correct
8 Correct 0 ms 348 KB Output is correct
9 Correct 0 ms 348 KB Output is correct
10 Correct 0 ms 344 KB Output is correct
11 Correct 0 ms 344 KB Output is correct
12 Correct 0 ms 348 KB Output is correct
13 Correct 0 ms 348 KB Output is correct
14 Correct 0 ms 348 KB Output is correct
15 Correct 0 ms 348 KB Output is correct
16 Correct 1 ms 344 KB Output is correct
17 Correct 0 ms 348 KB Output is correct
18 Correct 0 ms 348 KB Output is correct
19 Correct 1 ms 348 KB Output is correct
20 Correct 0 ms 348 KB Output is correct
21 Correct 0 ms 348 KB Output is correct
22 Correct 0 ms 348 KB Output is correct
23 Correct 0 ms 348 KB Output is correct
24 Correct 0 ms 348 KB Output is correct
25 Correct 0 ms 348 KB Output is correct
26 Correct 1 ms 348 KB Output is correct
27 Correct 0 ms 412 KB Output is correct
28 Correct 0 ms 348 KB Output is correct
29 Correct 0 ms 348 KB Output is correct
30 Correct 4 ms 860 KB Output is correct
31 Correct 4 ms 860 KB Output is correct
32 Correct 5 ms 860 KB Output is correct
33 Correct 4 ms 784 KB Output is correct
34 Correct 4 ms 956 KB Output is correct
35 Correct 2 ms 604 KB Output is correct
36 Correct 2 ms 604 KB Output is correct
37 Correct 2 ms 692 KB Output is correct
38 Correct 2 ms 676 KB Output is correct
39 Correct 2 ms 604 KB Output is correct
40 Correct 2 ms 688 KB Output is correct
41 Correct 3 ms 700 KB Output is correct
42 Correct 3 ms 704 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 254 ms 26736 KB Output is correct
2 Correct 266 ms 26792 KB Output is correct
3 Correct 251 ms 26736 KB Output is correct
4 Correct 285 ms 26992 KB Output is correct
5 Correct 248 ms 27244 KB Output is correct
6 Correct 246 ms 26224 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 538 ms 53728 KB Output is correct
2 Correct 576 ms 52956 KB Output is correct
3 Correct 541 ms 53060 KB Output is correct
4 Correct 549 ms 53080 KB Output is correct
5 Correct 559 ms 53340 KB Output is correct
6 Correct 550 ms 50396 KB Output is correct
7 Correct 552 ms 52700 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 344 KB Output is correct
2 Correct 1 ms 344 KB Output is correct
3 Correct 0 ms 348 KB Output is correct
4 Correct 1 ms 420 KB Output is correct
5 Correct 0 ms 348 KB Output is correct
6 Correct 0 ms 344 KB Output is correct
7 Correct 0 ms 348 KB Output is correct
8 Correct 0 ms 348 KB Output is correct
9 Correct 0 ms 348 KB Output is correct
10 Correct 0 ms 344 KB Output is correct
11 Correct 0 ms 344 KB Output is correct
12 Correct 0 ms 348 KB Output is correct
13 Correct 0 ms 348 KB Output is correct
14 Correct 0 ms 348 KB Output is correct
15 Correct 0 ms 348 KB Output is correct
16 Correct 1 ms 344 KB Output is correct
17 Correct 0 ms 348 KB Output is correct
18 Correct 0 ms 348 KB Output is correct
19 Correct 1 ms 348 KB Output is correct
20 Correct 0 ms 348 KB Output is correct
21 Correct 0 ms 348 KB Output is correct
22 Correct 0 ms 348 KB Output is correct
23 Correct 0 ms 348 KB Output is correct
24 Correct 0 ms 348 KB Output is correct
25 Correct 0 ms 348 KB Output is correct
26 Correct 1 ms 348 KB Output is correct
27 Correct 0 ms 412 KB Output is correct
28 Correct 0 ms 348 KB Output is correct
29 Correct 0 ms 348 KB Output is correct
30 Correct 4 ms 860 KB Output is correct
31 Correct 4 ms 860 KB Output is correct
32 Correct 5 ms 860 KB Output is correct
33 Correct 4 ms 784 KB Output is correct
34 Correct 4 ms 956 KB Output is correct
35 Correct 2 ms 604 KB Output is correct
36 Correct 2 ms 604 KB Output is correct
37 Correct 2 ms 692 KB Output is correct
38 Correct 2 ms 676 KB Output is correct
39 Correct 2 ms 604 KB Output is correct
40 Correct 2 ms 688 KB Output is correct
41 Correct 3 ms 700 KB Output is correct
42 Correct 3 ms 704 KB Output is correct
43 Correct 254 ms 26736 KB Output is correct
44 Correct 266 ms 26792 KB Output is correct
45 Correct 251 ms 26736 KB Output is correct
46 Correct 285 ms 26992 KB Output is correct
47 Correct 248 ms 27244 KB Output is correct
48 Correct 246 ms 26224 KB Output is correct
49 Correct 538 ms 53728 KB Output is correct
50 Correct 576 ms 52956 KB Output is correct
51 Correct 541 ms 53060 KB Output is correct
52 Correct 549 ms 53080 KB Output is correct
53 Correct 559 ms 53340 KB Output is correct
54 Correct 550 ms 50396 KB Output is correct
55 Correct 552 ms 52700 KB Output is correct
56 Correct 283 ms 26104 KB Output is correct
57 Correct 271 ms 26508 KB Output is correct
58 Correct 277 ms 26952 KB Output is correct
59 Correct 263 ms 25456 KB Output is correct
60 Correct 258 ms 26736 KB Output is correct
61 Correct 278 ms 27000 KB Output is correct
62 Correct 258 ms 25312 KB Output is correct
63 Correct 271 ms 26984 KB Output is correct
64 Correct 290 ms 26704 KB Output is correct
65 Correct 289 ms 27308 KB Output is correct
66 Correct 347 ms 28416 KB Output is correct
67 Correct 368 ms 29696 KB Output is correct
68 Correct 592 ms 50268 KB Output is correct
69 Correct 627 ms 52048 KB Output is correct
70 Correct 440 ms 47536 KB Output is correct