제출 #1343343

#제출 시각아이디문제언어결과실행 시간메모리
1343343jmuzhenHedgehog Daniyar and Algorithms (IZhO19_sortbooks)C++20
17 / 100
3098 ms327680 KiB
#define DEBUG 0

#if (!DEBUG) 
#pragma GCC optimize("O3,unroll-loops")
#endif

#include<bits/stdc++.h>
using namespace std;

#define int long long

#define printf if(DEBUG) printf
#define cerr if(DEBUG) cerr

template <typename T>
void print(const T& c) {
    for (const auto& e : c) {
        cerr << e << " ";
    } cerr << '\n';
}

#if DEBUG
    #define dbg(x) cerr << #x << " = " << (x) << endl
    #define dbg_c(v) cerr << #v << " : "; print(v)
#else
    #define dbg(x)
    #define dbg_c(v)
#endif


vector<int> a;

// Persistent segment tree for point updates and range sum-like queries over versions. 0-indexed.
// Usage: PersistentSegTree<long long> pst(n);
//        int root0 = pst.build(a);              // or pst.build_zero();
//        int root1 = pst.add(root0,pos,delta);  // new version, old root0 still valid
//        auto res = pst.query(root1,l,r);       // sum on [l,r] in that version.

template <class T>
struct PersistentSegTree {
    struct Node {
        T val; int l, r;
        Node(T v=T(),int _l=-1,int _r=-1): val(v),l(_l),r(_r) {}
    };
    int n; std::vector<Node> st;
    PersistentSegTree(int _n=0): n(_n) {
        if (n>0) st.reserve(20*n);
    }
    void init(int _n) {
        n=_n; st.clear();
        if (n>0) st.reserve(20*n);
    }
    int build_zero() { return -1; } // lazy create
    template <class Vec>
    int build(const Vec& a) { // a.size() must be == n
        return build(0,n-1,a);
    }
    template <class Vec>
    int build(int s,int e,const Vec& a) {
        int id = (int)st.size();
        st.emplace_back(T(),-1,-1);
        if (s==e) {
            st[id].val = (T)a[s];
        } else {
            int m=(s+e)>>1;
            st[id].l = build(s,m,a); st[id].r = build(m+1,e,a);
            pull(id);
        } return id;
    }
    void pull(int id) {
        T v=T();
        if (st[id].l!=-1) v += st[st[id].l].val;
        if (st[id].r!=-1) v += st[st[id].r].val;
        st[id].val = v;
    }
    int add(int root,int pos,T delta) { // point add: a[pos] += delta
        return add(root,0,n-1,pos,delta);
    }
    int add(int id,int s,int e,int pos,T delta) {
        int cur; if (id==-1) {
            cur = (int)st.size();
            st.emplace_back(T(),-1,-1);
        } else {
            cur = (int)st.size();
            st.push_back(st[id]); // clone
        }
        if (s==e) {
            st[cur].val += delta; return cur;
        }
        int m=(s+e)>>1; if (pos<=m) {
            int ch = (id==-1 ? -1 : st[id].l);
            st[cur].l = add(ch,s,m,pos,delta);
        } else {
            int ch = (id==-1 ? -1 : st[id].r);
            st[cur].r = add(ch,m+1,e,pos,delta);
        }
        pull(cur); return cur;
    }
    int set(int root,int pos,T v) { // point set: a[pos] = v
        return set(root,0,n-1,pos,v);
    }
    int set(int id,int s,int e,int pos,T v) {
        int cur;
        if (id==-1) {
            cur = (int)st.size();
            st.emplace_back(T(),-1,-1);
        } else {
            cur = (int)st.size();
            st.push_back(st[id]); // clone
        }
        if (s==e) {
            st[cur].val = v; return cur;
        }
        int m=(s+e)>>1;
        if (pos<=m) {
            int ch = (id==-1 ? -1 : st[id].l);
            st[cur].l = set(ch,s,m,pos,v);
        } else {
            int ch = (id==-1 ? -1 : st[id].r);
            st[cur].r = set(ch,m+1,e,pos,v);
        }
        pull(cur); return cur;
    }
    T query(int root,int l,int r) const { // range sum on [l,r]
        return query(root,0,n-1,l,r);
    }
    T query(int id,int s,int e,int l,int r) const {
        if (id==-1 || r<s || e<l) return T();
        if (l<=s && e<=r) return st[id].val;
        int m=(s+e)>>1; T res=T();
        if (l<=m) res += query(st[id].l,s,m,l,r);
        if (r>m)  res += query(st[id].r,m+1,e,l,r);
        return res;
    }
};

template <class T = int>
struct SubarrayOrderStats {
    struct S {
        int cnt; long long sum;
        S(int c = 0, long long s = 0) : cnt(c), sum(s) {}
        S& operator+=(const S& o) { cnt += o.cnt; sum += o.sum; return *this; }
    };

    PersistentSegTree<S> pst;
    vector<T> vals;
    vector<int> roots; // roots[i] = data for a[0..i-1]
    int n = 0, m = 0;

    SubarrayOrderStats() = default;
    explicit SubarrayOrderStats(const vector<T>& a) { build(a); }

    void build(const vector<T>& a) {
        n = (int)a.size(); vals = a;
        sort(vals.begin(), vals.end());
        vals.erase(unique(vals.begin(), vals.end()), vals.end());
        m = (int)vals.size(); pst.init(m);
        roots.assign(n + 1, -1); if (m == 0) return;
        roots[0] = pst.build_zero();
        for (int i = 0; i < n; i++) {
            int p = (int)(lower_bound(vals.begin(), vals.end(), a[i]) - vals.begin());
            roots[i + 1] = pst.add(roots[i], p, S(1, (long long)a[i]));
        }
    }

    int countRange(int l, int r, const T& x, const T& y) const {
        if (l > r || x > y || m == 0) return 0;
        int L = (int)(lower_bound(vals.begin(), vals.end(), x) - vals.begin());
        int R = (int)(upper_bound(vals.begin(), vals.end(), y) - vals.begin()) - 1;
        if (L > R) return 0;
        return pst.query(roots[r + 1], L, R).cnt - pst.query(roots[l], L, R).cnt;
    }

    T kthSmallest(int l, int r, int k) const {
        if (l > r || m == 0) throw out_of_range("kthSmallest on empty range");
        if (k < 1 || k > r - l + 1) throw out_of_range("k out of range");
        int idR = roots[r + 1], idL = roots[l], s = 0, e = m - 1;
        while (s < e) {
            int mid = (s + e) >> 1;
            int lR = (idR == -1 ? -1 : pst.st[idR].l), lL = (idL == -1 ? -1 : pst.st[idL].l);
            int c = cnt(lR) - cnt(lL);
            if (k <= c) idR = lR, idL = lL, e = mid;
            else k -= c, idR = right(idR), idL = right(idL), s = mid + 1;
        }
        return vals[s];
    }

    long long sumSmallestK(int l, int r, int k) const {
        if (l > r || m == 0) {
            if (k == 0) return 0;
            throw out_of_range("sumSmallestK on empty range");
        }
        if (k < 0 || k > r - l + 1) throw out_of_range("k out of range");
        if (k == 0) return 0;
        long long ans = 0;
        int idR = roots[r + 1], idL = roots[l], s = 0, e = m - 1;
        while (s < e && k > 0) {
            int mid = (s + e) >> 1;
            int lR = (idR == -1 ? -1 : pst.st[idR].l), lL = (idL == -1 ? -1 : pst.st[idL].l);
            int c = cnt(lR) - cnt(lL); long long ss = sum(lR) - sum(lL);
            if (k <= c) idR = lR, idL = lL, e = mid;
            else ans += ss, k -= c, idR = right(idR), idL = right(idL), s = mid + 1;
        }
        return ans + 1LL * k * (long long)vals[s];
    }

private:
    int right(int id) const { return id == -1 ? -1 : pst.st[id].r; }
    int cnt(int id) const { return id == -1 ? 0 : pst.st[id].val.cnt; }
    long long sum(int id) const { return id == -1 ? 0LL : pst.st[id].val.sum; }
};

SubarrayOrderStats<int> *os;


inline int max_lt(int x, int y, int t) {
    int l = 0, r = t;
    int best = -1;
    while (l <= r) {
        int mid = l+(r-l)/2;
        // is there some value in mid..t-1?
        bool ok = os->countRange(x, y, mid, t-1) > 0;
        if (ok) {
            // we can increase mid
            best = mid;
            l = mid+1;
        } else {
            r = mid-1;
        }
    }
    return best;
}

struct Seg{
    struct Info {
        int cost = 0;
        int mx = -1;
    };

  int s, e,m;
  Seg *l, *r;
  Info info;

  Info merge(const Info &l, const Info &r, int rl, int rr) {
    Info c{};
    c.cost = max(l.cost, r.cost);
    c.mx = max(l.mx, r.mx);

    if (l.mx != -1) {
        // LAST in r less than l_max
        // call another st
        int r_max_lt = max_lt(rl, rr, l.mx);
        if (r_max_lt != -1) {
            c.cost = max(c.cost, l.mx + r_max_lt);
        }
    }
    return c;
  }

  Seg (int s, int e, vector<int> &a) {
    this->s = s;this->e = e;
    m=(s+e)/2;
    if (s!=e) {
        l = new Seg(s,m, a);
        r = new Seg(m+1, e, a);
        info = merge(l->info, r->info, r->s, r->e);
    } else {
        info = Info{};
        info.mx = a[s];
    }
  }

  Info query(int x, int y) {
    if (x <= s && e <= y) {
        return info;
    }
    if (y < s || e < x) {
        return Info{};
    }

    if (x > m) return r->query(x,y);
    if (y < m) return l->query(x,y);

    int rl = max(r->s, x);
    int rr = min(r->e, y);

    return merge(l->query(x,y), r->query(rl,rr), rl, rr);
  }

};

signed main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);
    int n,m;cin>>n>>m;
    a.resize(n);
    for (int i = 0; i < n; i++) cin>>a[i];
    os = new SubarrayOrderStats(a);
    
    Seg seg(0, n-1, a);
    for (int i = 0; i < m; i++) {
        int l,r,k;cin>>l>>r>>k; l--,r--;
        auto q = seg.query(l,r);
        printf("cost %d\n",q.cost);
        cout<<(q.cost <= k ? 1 : 0)<<"\n";
    }
}

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

sortbooks.cpp: In function 'int main()':
sortbooks.cpp:303:23: warning: format '%d' expects argument of type 'int', but argument 2 has type 'long long int' [-Wformat=]
  303 |         printf("cost %d\n",q.cost);
      |                      ~^    ~~~~~~
      |                       |      |
      |                       int    long long int
      |                      %lld
#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...