답안 #234608

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
234608 2020-05-24T19:10:10 Z ne4eHbKa Plahte (COCI17_plahte) C++17
96 / 160
2000 ms 231428 KB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

template<typename t> inline void umin(t &a, t b) {a = min(a, b);}
template<typename t> inline void umax(t &a, t b) {a = max(a, b);}

#define re return
#define ft first
#define sd second

mt19937 rnd(chrono::system_clock().now().time_since_epoch().count());

int rint(int v) {re rnd() % v;}

const int N = 8e4 + 5;

int n, m, mxx, mxy, mxc;
vector<int> p;
vector<ll> area;

map<int, int> shrink_x, shrink_y, shrink_c;

struct rect {
    int x, y, X, Y;
    rect() {
        cin >> x >> y >> X >> Y;
        shrink_x[x], shrink_x[X];
        shrink_y[y], shrink_y[Y];
    }
    void init(ll *a) {
        x = shrink_x[x];
        X = shrink_x[X];
        y = shrink_y[y];
        Y = shrink_y[Y];
        (*a = X - x) *= (ll)Y - y;
    }
};

vector<rect> rects;

struct ball {
    int x, y, c;
    ball() {
        cin >> x >> y >> c;
        shrink_x[x];
        shrink_y[y];
        shrink_c[c];
    }
    void init() {
        x = shrink_x[x];
        y = shrink_y[y];
        c = shrink_c[c];
    }
};

vector<ball> balls;

struct cmp {
    bool operator() (const int &a, const int &b) const {
        return area[a] == area[b]
            ? a < b
            : area[a] < area[b];
    }
};

int cur, upper_rect;

struct tree {
    tree *l, *r;
    set<int, cmp> v {}, f {};
    tree(int tl = 0, int tr = mxy - 1): l(r = 0) {
        if(tl < tr) {
            int tm = (tl + tr) >> 1;
            l = new tree(tl, tm);
            r = new tree(tm + 1, tr);
        }
    }
    void add(int ql, int qr, int tl = 0, int tr = mxy - 1) {
        if(ql > qr) re;
        if(!f.empty()) {
            int u = *f.begin();
            if(upper_rect < 0 || area[upper_rect] > area[u])
                upper_rect = u;
        }
        if(ql == tl && qr == tr) {
            f.insert(cur);
            if(!v.empty()) {
                int u = *v.begin();
                if(upper_rect < 0 || area[upper_rect] > area[u])
                    upper_rect = u;
            }
        } else {
            v.insert(cur);
            int tm = (tl + tr) >> 1;
            l->add(ql, min(qr, tm), tl, tm);
            r->add(max(tm + 1, ql), qr, tm + 1, tr);
        }
    }
    void del(int ql, int qr, int tl = 0, int tr = mxy - 1) {
        if(ql > qr) re;
        if(ql == tl && qr == tr) re void(f.erase(cur));
        v.erase(cur);
        if(tl < tr) {
            int tm = (tl + tr) >> 1;
            l->del(ql, min(qr, tm), tl, tm);
            r->del(max(tm + 1, ql), qr, tm + 1, tr);
        }
    }
    void shoot(int p, int tl = 0, int tr = mxy - 1) {
        if(!f.empty()) {
            int u = *f.begin();
            if(cur < 0 || area[cur] > area[u])
                cur = u;
        }
        if(tl == tr) re;
        int tm = (tl + tr) >> 1;
        p <= tm
            ? l->shoot(p, tl, tm)
            : r->shoot(p, tm + 1, tr);
    }
};

vector<int> g[N];
vector<int> nodes[N];

int l[N + N], r[N + N], timer, st[18][N + N], h[N], lg[N + N], rt[N], root;

void rec(int v, int he = 0) {
    rt[v] = root, h[v] = he;
    st[0][l[v] = r[v] = timer++] = v;
    for(const int &u : g[v]) {
        rec(u, he + 1);
        st[0][r[v] = timer++] = v;
    }
}

int mn(int a, int b) {re h[a] < h[b] ? a : b;}

void build_sparse() {
    for(int i = 0; i < N + N; ++i) lg[i] = !i ? 0 : lg[i - 1] + (1 << lg[i - 1] + 1 <= i);
    for(int j = 1; j < 18; ++j) for(int i = 0; i + (1 << j) - 1 < N + N; ++i)
        st[j][i] = mn(st[j - 1][i], st[j - 1][i + (1 << j - 1)]);
}

int lca(int a, int b) {
    if(l[a] > l[b]) swap(a, b);
    if(r[a] >= r[b]) re a;
    int f = lg[r[b] - l[a] + 1];
    re mn(st[f][l[a]], st[f][r[b] - (1 << f) + 1]);
}

int z[N];
int count(int v) { for(int u : g[v]) z[v] += count(u); re z[v]; }

int main() {
#ifdef _LOCAL
    freopen("10.in", "r", stdin);
    freopen("10.out", "w", stdout);
#endif // _LOCAL

    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);

    cin >> n >> m;
    for(int i = 0; i < n; ++i) rects.emplace_back();
    for(int i = 0; i < m; ++i) balls.emplace_back();

    for(auto t : shrink_x) shrink_x[t.ft] = mxx++;
    for(auto t : shrink_y) shrink_y[t.ft] = mxy++;
    for(auto t : shrink_c) shrink_c[t.ft] = mxc++;

    area.resize(n);
    ll *pt_a = &area[0];
    for(auto &t : rects) t.init(pt_a++);
    for(auto &t : balls) t.init();

    tree t {};

    vector<int> rect_add(n);
    for(int i = 0; i < n; ++i) rect_add[i] = i;
    sort(rect_add.begin(), rect_add.end(),
        [&] (const int &a, const int &b) {return rects[a].x != rects[b].x
            ? rects[a].x < rects[b].x
            : area[a] > area[b];});

    vector<int> rect_del = rect_add;
    sort(rect_del.begin(), rect_del.end(),
        [&] (const int &a, const int &b) {return rects[a].X < rects[b].X;});

    vector<int> shot(m);
    for(int i = 0; i < m; ++i) shot[i] = i;
    sort(shot.begin(), shot.end(),
        [&] (const int &a, const int &b) {return balls[a].x < balls[b].x;});

    p.assign(n, -1);

    int ai = 0, di = 0, si = 0;
    for(int x = 0; x < mxx; ++x) {
        for(; ai < n && rects[rect_add[ai]].x == x; ++ai) {
            cur = rect_add[ai];
            upper_rect = -1;
            t.add(rects[cur].y, rects[cur].Y);
            p[cur] = upper_rect;
//            cerr << "add " << rects[cur].y << ' ' << rects[cur].Y << endl;
        }
        for(; si < m && balls[shot[si]].x == x; ++si) {
            cur = -1;
            t.shoot(balls[shot[si]].y);
            if(~cur) nodes[balls[shot[si]].c].push_back(cur);
//            cerr << "shoot " << balls[shot[si]].c << ' ' << balls[shot[si]].y << endl;
        }
        for(; di < n && rects[rect_del[di]].X == x; ++di) {
            cur = rect_del[di];
            t.del(rects[cur].y, rects[cur].Y);
//            cerr << "del " << rects[cur].y << ' ' << rects[cur].Y << endl;
        }
    }

    for(int i = 0; i < n; ++i) if(~p[i]) g[p[i]].push_back(i);

    for(int i = 0; i < n; ++i) if(p[i] < 0) root = i, rec(i);

    build_sparse();

    for(int c = 0; c < mxc; c++) {
        vector<int> &ns = nodes[c];
        sort(ns.begin(), ns.end(), [&] (const int &a, const int &b) {return l[a] < l[b];});
        int v = -1;
        for(int i : ns) v < 0 || rt[v] != rt[i]
                            ? z[v = i]++
                            : (z[i]++, z[lca(i, v)]--, v = i);
    }

    for(int i = 0; i < n; ++i) if(p[i] < 0) count(i);

    for(int i = 0; i < n; ++i) cout << z[i] << '\n';
}

Compilation message

plahte.cpp: In function 'void build_sparse()':
plahte.cpp:143:81: warning: suggest parentheses around '+' inside '<<' [-Wparentheses]
     for(int i = 0; i < N + N; ++i) lg[i] = !i ? 0 : lg[i - 1] + (1 << lg[i - 1] + 1 <= i);
                                                                       ~~~~~~~~~~^~~
plahte.cpp:145:59: warning: suggest parentheses around '-' inside '<<' [-Wparentheses]
         st[j][i] = mn(st[j - 1][i], st[j - 1][i + (1 << j - 1)]);
                                                         ~~^~~
# 결과 실행 시간 메모리 Grader output
1 Correct 400 ms 50084 KB Output is correct
2 Correct 365 ms 42604 KB Output is correct
3 Correct 15 ms 14464 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 596 ms 84592 KB Output is correct
2 Correct 539 ms 64112 KB Output is correct
3 Correct 16 ms 14464 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1168 ms 148304 KB Output is correct
2 Correct 980 ms 82492 KB Output is correct
3 Correct 17 ms 14464 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 2087 ms 231428 KB Time limit exceeded
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 2043 ms 206924 KB Time limit exceeded
2 Halted 0 ms 0 KB -