Submission #559824

#TimeUsernameProblemLanguageResultExecution timeMemory
559824emuyumiTeams (IOI15_teams)C++17
100 / 100
3566 ms175740 KiB
#include <bits/stdc++.h>

using namespace std;
using ll = long long;

struct Segtree{

#define mid ((l + r) >> 1)

    struct Node{
        int lc, rc, val;
    };

    int N;
    vector<Node> st;
    int T;

    Segtree() = default;
    Segtree(int N) : N(N) {
        st.resize(25 * N);
        T = 0;

        build(0, 1, N);
    }

    int build(int v, int l, int r){
        if (l == r) return v;
        st[v].lc = build(++T, l, mid);
        st[v].rc = build(++T, mid + 1, r);
        return v;
    }

    int insert(int v, int l, int r, int idx){
        int nv = ++T;
        if (l == r){
            st[nv] = {0, 0, st[v].val + 1};
        }
        else if (idx <= mid){
            st[nv].lc = insert(st[v].lc, l, mid, idx);
            st[nv].rc = st[v].rc;
            st[nv].val = st[st[nv].lc].val + st[st[nv].rc].val;
        }
        else{
            st[nv].lc = st[v].lc;
            st[nv].rc = insert(st[v].rc, mid + 1, r, idx);
            st[nv].val = st[st[nv].lc].val + st[st[nv].rc].val;
        }
        return nv;
    }
    int insert(int v, int idx){ return insert(v, 1, N, idx); }

    int query(int vl, int vr, int l, int r, int ql, int qr){
        if (l > qr || r < ql || ql > qr) return 0;
        if (l >= ql && r <= qr) return st[vr].val - st[vl].val;
        return query(st[vl].lc, st[vr].lc, l, mid, ql, qr) +
               query(st[vl].rc, st[vr].rc, mid + 1, r, ql, qr);
    }
    int query(int vl, int vr, int ql, int qr){ return query(vl, vr, 1, N, ql, qr); }

#undef mid
};

using pii = pair<int, int>;

Segtree st;
vector<int> rts;
int N;
vector<pii> xs, ys;

void init(int N, int A[], int B[]){
    ::N = N;

    for (int i = 0; i < N; ++i){
        xs.push_back({A[i], i});
        ys.push_back({B[i], i});
    }

    // give each point unique x and unique y
    sort(xs.begin(), xs.end());
    sort(ys.begin(), ys.end());

    vector<int> y(N + 1);
    for (int i = 0; i < N; ++i){
        int x = lower_bound(xs.begin(), xs.end(), pii{A[i], i}) - xs.begin() + 1;
        y[x] = lower_bound(ys.begin(), ys.end(), pii{B[i], i}) - ys.begin() + 1;
// cerr << x << " " << y[x] << '\n';
    }

    st = Segtree(N + 1);
    rts.resize(N + 1);
    int v = 0;

    for (int x = 1; x <= N; ++x){
        v = st.insert(v, y[x]);
        rts[x] = v;
    }
}

// number of points in [x1, x2] x [y1, y2]
int count(int x1, int x2, int y1, int y2){
    x2 = min(x2, N);
    y2 = min(y2, N);
    return st.query(rts[x1 - 1], rts[x2], y1, y2);
}

int can(int M, int K[]){
    sort(K, K + M);
    struct Point{ int x, y; };

    vector<Point> stk = {};
    stk.push_back({0, N + 1});

    for (int i = 0; i < M; ++i){
        int qx = upper_bound(xs.begin(), xs.end(), pii{K[i], 1e9}) - xs.begin() + 1 - 1;
        int qy = lower_bound(ys.begin(), ys.end(), pii{K[i], -1}) - ys.begin() + 1;

        while (stk.back().y < qy){
            stk.pop_back();
        }

        int need = K[i];
        while (need){
            if (stk.empty()){
                return 0;
            }
            auto [lx, ly] = stk.back();

            /*
            
            **........^
            **........^
            *****%%%%%% ly
            *****%%%%%% qy
            ***********
            ***********
                lx    qx
            */
            int rect = count(lx + 1, qx, qy, ly);
// cerr << lx + 1 << " " << qx << " " << qy << " " << ly << '\n';
// cerr << rect << '\n';
            if (rect <= need){
                need -= rect;
                qy = ly + 1;
                stk.pop_back();
            }
            else{
                // bsearch for new y
                int lo = qy - 1, hi = ly;
                while (lo < hi){
                    int mi = (lo + hi) >> 1;
                    int cnt = count(lx + 1, qx, qy, mi);
                    if (cnt >= need) hi = mi;
                    else lo = mi + 1;
                }
                need = 0;
                qy = lo + 1;
            }
        }
        stk.push_back({qx, qy - 1});
    }
    return 1;
}

Compilation message (stderr)

teams.cpp: In constructor 'Segtree::Segtree(int)':
teams.cpp:19:17: warning: declaration of 'N' shadows a member of 'Segtree' [-Wshadow]
   19 |     Segtree(int N) : N(N) {
      |             ~~~~^
teams.cpp:14:9: note: shadowed declaration is here
   14 |     int N;
      |         ^
teams.cpp: In constructor 'Segtree::Segtree(int)':
teams.cpp:19:17: warning: declaration of 'N' shadows a member of 'Segtree' [-Wshadow]
   19 |     Segtree(int N) : N(N) {
      |             ~~~~^
teams.cpp:14:9: note: shadowed declaration is here
   14 |     int N;
      |         ^
teams.cpp: In constructor 'Segtree::Segtree(int)':
teams.cpp:19:17: warning: declaration of 'N' shadows a member of 'Segtree' [-Wshadow]
   19 |     Segtree(int N) : N(N) {
      |             ~~~~^
teams.cpp:14:9: note: shadowed declaration is here
   14 |     int N;
      |         ^
teams.cpp: In function 'void init(int, int*, int*)':
teams.cpp:70:15: warning: declaration of 'N' shadows a global declaration [-Wshadow]
   70 | void init(int N, int A[], int B[]){
      |           ~~~~^
teams.cpp:67:5: note: shadowed declaration is here
   67 | int N;
      |     ^
teams.cpp:84:78: warning: conversion from '__gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int> > >::difference_type' {aka 'long int'} to 'int' may change value [-Wconversion]
   84 |         int x = lower_bound(xs.begin(), xs.end(), pii{A[i], i}) - xs.begin() + 1;
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
teams.cpp:85:77: warning: conversion from '__gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int> > >::difference_type' {aka 'long int'} to '__gnu_cxx::__alloc_traits<std::allocator<int>, int>::value_type' {aka 'int'} may change value [-Wconversion]
   85 |         y[x] = lower_bound(ys.begin(), ys.end(), pii{B[i], i}) - ys.begin() + 1;
      |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
teams.cpp: In function 'int can(int, int*)':
teams.cpp:114:85: warning: conversion from '__gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int> > >::difference_type' {aka 'long int'} to 'int' may change value [-Wconversion]
  114 |         int qx = upper_bound(xs.begin(), xs.end(), pii{K[i], 1e9}) - xs.begin() + 1 - 1;
      |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
teams.cpp:115:80: warning: conversion from '__gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int> > >::difference_type' {aka 'long int'} to 'int' may change value [-Wconversion]
  115 |         int qy = lower_bound(ys.begin(), ys.end(), pii{K[i], -1}) - ys.begin() + 1;
      |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...