제출 #1127285

#제출 시각아이디문제언어결과실행 시간메모리
1127285RiverFlowTricks of the Trade (CEOI23_trade)C++20
100 / 100
1195 ms203872 KiB
#include <bits/stdc++.h>

#define nl "\n"
#define no "NO"
#define yes "YES"
#define fi first
#define se second
#define vec vector
#define task "main"
#define _mp make_pair
#define ii pair<int, int>
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
#define evoid(val) return void(std::cout << val)
#define FOR(i, a, b) for(int i = (a); i <= (b); ++i)
#define FOD(i, b, a) for(int i = (b); i >= (a); --i)
#define unq(x) sort(all(x)); x.resize(unique(all(x)) - x.begin())

using namespace std;

template<typename U, typename V> bool maxi(U &a, V b) {
    if (a < b) { a = b; return 1; } return 0;
}
template<typename U, typename V> bool mini(U &a, V b) {
    if (a > b) { a = b; return 1; } return 0;
}

const int N = (int)250000 + 9;
const int mod = (int)1e9 + 7;

void prepare(); void main_code();

int main() {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    if (fopen(task".inp", "r")) {
        freopen(task".inp", "r", stdin);
        freopen(task".out", "w", stdout);
    }
    const bool MULTITEST = 0; prepare();
    int num_test = 1; if (MULTITEST) cin >> num_test;
    while (num_test--) { main_code(); }
}

void prepare() {};

int n, k, c[N];
long long s[N];

int ver[N], vl[N];

const long long INF = (long long)-1e15;

struct persis {
    struct node {
        int l, r;
        int cnt = 0;
        long long sum = 0;
        node () {
            l = r = -1;
        }
        void cp(node &x) {
            l = x.l, r = x.r;
            cnt = x.cnt;
            sum = x.sum;
        }
    };
    int N;
    vector<node> t;
    int build(int l, int r) {
        int cur = sz(t);
        t.push_back(node());
        if (l == r) return cur;
        int m = (l + r) >> 1;
        int L = build(l, m);
        int R = build(m + 1, r);
        t[cur].l = L, t[cur].r = R;
//        cerr << l << ' ' << r << ' ' << cur << ' ' << t[cur].l << ' ' << t[cur].r << nl;
        return cur;
    }
    void refine(int id){
        t[id].cnt=t[t[id].l].cnt + t[t[id].r].cnt;
        t[id].sum=t[t[id].l].sum + t[t[id].r].sum;
    }
    int upd(int id, int l, int r, int p) {
        int cur = sz(t);
        t.push_back(node());
        t.back().cp(t[id]);
        if (l == r) {
            ++t[cur].cnt;
            t[cur].sum += vl[l];
            return cur;
        }
        int m = (l + r) >> 1;
        if (p <= m) {
            int x=upd(t[id].l, l, m, p);
            t[cur].l=x;
        }else{
            int x=upd(t[id].r, m+1, r, p);
            t[cur].r=x;
        }
        refine(cur);
//        cerr << l << ' ' << r << ' ' << p << ' ' << id << ' ' << t[cur].l << ' ' << t[cur].r << ' ' << t[id].sum << nl;
        return cur;
    }
    int upd(int id, int v) {
        return upd(id, 1, N, v);
    }
    void init() {

        vec<int> cc;
        FOR(i, 1, n) cc.push_back(c[i]);
        unq(cc);
        N = sz(cc);
        FOR(i, 1, N) vl[i] = cc[i - 1];
        ver[0] = build(1, N);

        FOR(i, 1, n) {
            int x = lower_bound(all(cc), c[i]) - cc.begin() + 1;
            ver[i] = upd(ver[i - 1], x);
        }
    }
    #define rc(id) (t[id].r)
    #define lc(id) (t[id].l)
    pair<long long, int> get(int id1, int id2, int l, int r, int k) {
        if (l == r) return _mp(1LL * k * vl[l], vl[l]);
        int m = (l + r) >> 1;
        if (t[rc(id1)].cnt - t[rc(id2)].cnt >= k)
            return get(rc(id1), rc(id2), m + 1, r, k);
        auto A = _mp(t[rc(id1)].sum - t[rc(id2)].sum, t[rc(id1)].cnt - t[rc(id2)].cnt);
        auto B = get(lc(id1), lc(id2), l, m, k - A.second);
        return _mp(A.fi + B.fi, B.se);
    }
    pair<long long, int> get(int l, int r) {
        if (r - l + 1 < k) return _mp(INF, 0);
        return get(ver[r], ver[l - 1], 1, N, k);
    }

};

persis st;
long long ans = INF;

int opt[N];
long long dp[N];

void solve(int l, int r, int lb, int rb) {
    if (l > r) return ;
    int mid = (l + r) / 2;
    pair<long long, int> mx = {2LL * INF, -rb};
    FOR(i, max(mid + k - 1, lb), rb) {
        mx = max(mx, _mp(st.get(mid, i).first - (s[i] - s[mid - 1]), -i));
    }
//    cerr << l << ' ' << r << ' ' << lb << ' ' << rb << nl;
    dp[mid] = mx.first;
    opt[mid] = -mx.second;
    maxi(ans, dp[mid]);

    solve(l, mid - 1, lb, opt[mid]);
    solve(mid + 1, r, opt[mid], rb);
}

int res[N];

struct segment_tree {
    const int MX = (int)1e9 + 7;
    int n;
    vec<int> t;
    segment_tree () {};
    segment_tree (int _n) {
        n = _n;
        t.resize(n * 4 + 7);
        FOR(i, 1, 4 * n) t[i] = MX;
    }
    void update(int id, int l, int r, int u, int v, int val) {
        if (l > v or r < u) return ;
        if (l >= u and r <= v) {
            t[id] = min(t[id], val);
            return ;
        }
        int m = (l + r) >> 1;
        update(id << 1, l, m, u, v, val);
        update(id << 1 | 1, m + 1, r, u, v, val);
    }
    void update(int l, int r, int val) {
//        cerr << l << ' ' << r << ' ' << val << nl;
        update(1, 1, n, l, r, val);
//        cerr << l << ' ' << r << ' ' << val << nl;
    }
    void fin(int id, int l, int r) {
        if (l == r) {
            res[l] = c[l] >= t[id];
            return ;
        }
        t[id << 1] = min(t[id << 1], t[id]);
        t[id << 1 | 1] = min(t[id << 1 | 1], t[id]);
        int m = (l + r) >> 1;
        fin(id << 1, l, m);
        fin(id << 1 | 1, m + 1, r);
    }
};

void main_code() {
    cin >> n >> k;
    FOR(i, 1, n) cin >> s[i], s[i] += s[i - 1];
    FOR(i, 1, n) cin >> c[i];

    st.init();

    solve(1, n, 1, n);

    vec<int> p;
    FOR(i, 1, n) if (dp[i] == ans) {
        p.push_back(i);
    }
//    for(int x : p) cout << x << nl;
    segment_tree st2(n);
    FOR(i, 0, sz(p) - 2) {
        if (opt[p[i]] < p[i + 1]) {
            for(int j = opt[p[i]]; j <= opt[p[i+1]]; ++j) {
                auto g = st.get(p[i], j);
                long long x = g.first - (s[j] - s[p[i]-1]);
                if (x == ans) {
                    st2.update(p[i], j, g.se);
                }
            }
        } else {
            for(int j = opt[p[i]]; j <= opt[p[i+1]]; ++j) {
                auto g = st.get(p[i], j);
                long long x = g.first - (s[j] - s[p[i]-1]);
                if (x == ans) {
                    st2.update(p[i], j, g.se);
                }
            }
        }
    }
    FOR(j, opt[p.back()], n) {
        auto g = st.get(p.back(), j);
        long long x = g.first - (s[j] - s[p.back()-1]);
        if (x == ans) {
            st2.update(p.back(), j, g.se);
        }
    }
    cout << ans << nl;
    st2.fin(1, 1, n);

    FOR(i, 1, n) cout << res[i];
}


/*     Let the river flows naturally     */

컴파일 시 표준 에러 (stderr) 메시지

trade.cpp: In function 'int main()':
trade.cpp:36:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   36 |         freopen(task".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
trade.cpp:37:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   37 |         freopen(task".out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#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...