| # | Time | Username | Problem | Language | Result | Execution time | Memory | 
|---|---|---|---|---|---|---|---|
| 218743 | Vimmer | Matching (COCI20_matching) | C++14 | 0 ms | 0 KiB | 
This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
//#pragma GCC optimize("unroll-loops")
//#pragma GCC optimize("-O3")
//#pragma GCC optimize("Ofast")
#define F first
#define S second
#define sz(x) int(x.size())
#define pb push_back
#define N 100001
using namespace std;
int x[N], y[N], a[N][2], n, xr[N], yr[N];
set <int> tx[N * 4], ty[N * 4];
set <pair <int, int> > tx_del[N * 4], ty_del[N * 4];
vector <pair <int, char> > psh[N * 4];
vector <pair <pair <int, int>, char>  > psh_del[N * 4];
bool mk[N], mkr[N][2];
queue <int> alone;
vector <pair <int, int> > g, gr;
map <pair <int, int>, pair <int, int> > mp;
void Push(int v, int tl, int tr)
{
    while (sz(psh[v]) > 0)
    {
        pair <int, char> val = psh[v].back();
        psh[v].pop_back();
        if (val.S == 'a') tx[v].insert(val.F); else ty[v].insert(val.F);
        if (tl != tr) {psh[v + v].pb(val); psh[v + v + 1].pb(val);}
    }
}
void upd(int v, int tl, int tr, int l, int r, int val, bool f)
{
    Push(v, tl, tr);
    if (tl > tr || l > r || r < tl || tr < l) return;
    if (l <= tl && tr <= r) {if (!f) psh[v].pb({val, 'a'}); else psh[v].pb({val, 'b'}); Push(v, tl, tr); return;}
    int md = (tl + tr) >> 1;
    upd(v + v, tl, md, l, r, val, f);
    upd(v + v + 1, md + 1, tr, l, r, val, f);
}
void Push_del(int v, int tl, int tr)
{
    while (sz(psh_del[v]) > 0)
    {
        pair <pair <int, int>, char>  pt = psh_del[v].back();
        psh_del[v].pop_back();
        if (pt.S == 'a') tx_del[v].insert(pt.F); else if (pt.S == 'b') ty_del[v].insert(pt.F);
          else if (pt.S == 'c') tx_del[v].erase(pt.F); else ty_del[v].erase(pt.F);
        if (tl != tr) {psh_del[v + v].pb(pt); psh_del[v + v + 1].pb(pt); }
    }
}
void upd_del(int v, int tl, int tr, int l, int r, pair <int, int> val, bool f)
{
    Push_del(v, tl, tr);
    if (tl > tr || l > r || r < tl || tr < l) return;
    if (l <= tl && tr <= r) {if (!f) psh_del[v].pb({val, 'a'}); else psh_del[v].pb({val, 'b'}); Push_del(v, tl, tr); return;}
    int md = (tl + tr) >> 1;
    upd_del(v + v, tl, md, l, r, val, f);
    upd_del(v + v + 1, md + 1, tr, l, r, val, f);
}
void upd_remove(int v, int tl, int tr, int l, int r, pair <int, int> val, bool f)
{
    Push_del(v, tl, tr);
    if (tl > tr || l > r || r < tl || tr < l) return;
    if (l <= tl && tr <= r) {if (!f) psh_del[v].pb({val, 'c'}); else psh_del[v].pb({val, 'd'}); Push_del(v, tl, tr); return;}
    int md = (tl + tr) >> 1;
    upd_remove(v + v, tl, md, l, r, val, f);
    upd_remove(v + v + 1, md + 1, tr, l, r, val, f);
}
bool good(int v, int tl, int tr, int pos, int l, int r, bool f)
{
    Push(v, tl, tr);
    if (tl == tr)
    {
        set <int> :: iterator it;
        if (f)
        {
            it = ty[v].lower_bound(l);
            return (it == ty[v].end() ? 1 : *it > r);
        }
        else
        {
            it = tx[v].lower_bound(l);
            return (it == tx[v].end() ? 1 : *it > r);
        }
    }
    else
    {
        int md = (tl + tr) >> 1;
        if (pos <= md) return good(v + v, tl, md, pos, l, r, f);
        return good(v + v + 1, md + 1, tr, pos, l, r, f);
    }
}
int good_del(int v, int tl, int tr, int pos, int l, int r, bool f)
{
    Push_del(v, tl, tr);
    if (tl == tr)
    {
        set <pair <int, int> > :: iterator it;
        if (f)
        {
            it = ty_del[v].lower_bound({l, -1e9});
            if (it == ty_del[v].end() || (*it).F > r) return -1;
            return (*it).S;
        }
        else
        {
            it = tx_del[v].lower_bound({l, -1e9});
            if (it == tx_del[v].end() || (*it).F > r) return -1;
            return (*it).S;
        }
    }
    else
    {
        int md = (tl + tr) >> 1;
        if (pos <= md) return good_del(v + v, tl, md, pos, l, r, f);
        return good_del(v + v + 1, md + 1, tr, pos, l, r, f);
    }
}
bool gd(int fr, int sc)
{
    if (x[fr] == x[sc])
    {
        if (y[fr] > y[sc]) swap(fr, sc);
        return good(1, 1, N - 1, x[fr], y[fr], y[sc], 0);
    }
    else
    {
        if (x[fr] > x[sc]) swap(fr, sc);
        return good(1, 1, N - 1, y[fr], x[fr], x[sc], 1);
    }
}
void add_remove(int fr, int sc, int nm)
{
    if (!mk[fr]) alone.push(fr);
    if (!mk[sc]) alone.push(sc);
    if (x[fr] == x[sc])
    {
        if (y[fr] > y[sc]) swap(fr, sc);
        upd_remove(1, 1, N, y[fr], y[sc], {x[fr], nm }, 1);
        if (a[fr][1] != -1) upd_remove(1, 1, N, min(x[a[fr][1]], x[fr]), max(x[fr], x[a[fr][1]]), {y[fr], mp[{fr, a[fr][1]}]});
        if (a[sc][1] != -1) upd_remove(1, 1, N, min(x[a[sc][1]], x[sc]), max(x[sc], x[a[sc][1]]), {y[sc], mp[{sc, a[sc][1]}]});
    }
    else
    {
        if (x[fr] > x[sc]) swap(fr, sc);
        upd_remove(1, 1, N, x[fr], x[sc], {y[fr], nm }, 0);
        if (a[fr][0] != -1) upd_remove(1, 1, N, min(y[a[fr][0]], y[fr]), max(y[fr], y[a[fr][0]]), {x[fr], mp[{fr, a[fr][0]}]});
        if (a[sc][0] != -1) upd_remove(1, 1, N, min(y[a[sc][0]], y[sc]), max(y[sc], y[a[sc][0]]), {x[sc], mp[{sc, a[sc][0]}]});
    }
}
void seacrh(int fr, int sc)
{
    if (x[fr] == x[sc])
    {
        if (y[fr] > y[sc]) swap(fr, sc);
        int pt = good_del(1, 1, N, x[fr], y[fr], y[sc], 0);
        while (pt != -1)
        {
            add_remove(gr[pt].F, gr[pt].S, pt);
            pt = good_del(1, 1, N, x[fr], y[fr], y[sc], 0);
        }
    }
    else
    {
        if (x[fr] > x[sc]) swap(fr, sc);
        int pt = good_del(1, 1, N, y[fr], x[fr], x[sc], 1);
        while (pt != -1)
        {
            add_remove(gr[pt].F, gr[pt].S, pt);
            pt = good_del(1, 1, N, y[fr], x[fr], x[sc], 1);
        }
    }
}
void add(int fr, int sc)
{
    if (x[fr] == x[sc])
    {
        g.pb({fr, sc});
        if (y[fr] > y[sc]) swap(fr, sc);
        upd(1, 1, N - 1, y[fr], y[sc], x[fr], 1);
        seacrh(fr, sc);
    }
    else
    {
        g.pb({fr, sc});
        if (x[fr] > x[sc]) swap(fr, sc);
        upd(1, 1, N - 1, x[fr], x[sc], y[fr], 0);
        seacrh(fr, sc);
    }
}
void clr(int x)
{
    mk[x] = 1;
    if (a[x][1] != -1) {if (!mk[a[x][1]]) alone.push(a[x][1]); a[x][1] = a[a[x][1]][1] = -1;}
    if (a[x][0] != -1) {if (!mk[a[x][0]]) alone.push(a[x][0]); a[x][0] = a[a[x][0]][0] = -1;}
}
void fnd()
{
    while (sz(alone) > 0)
    {
        int v = alone.front();
        alone.pop();
        if (mk[v]) continue;
        if (a[v][1] != -1 && gd(v, a[v][1])) {add(v, a[v][1]); clr(a[v][1]); clr(v); continue;}
        if (a[v][0] != -1 && gd(v, a[v][0])) {add(v, a[v][0]); clr(a[v][0]); clr(v); continue;}
        cout << "NE" << endl;
        exit(0);
    }
    for (int i = 0; i < n; i++)
    {
        if (mk[i]) continue;
        g.pb({i, a[i][0]});
        clr(a[i][0]);
        clr(i);
    }
}
void add_del(int fr, int sc)
{
    if (x[fr] == x[sc])
    {
        if (mkr[fr][0]) return;
        mkr[fr][0] = 1;
        mkr[sc][0] = 1;
        if (y[fr] > y[sc]) swap(fr, sc);
        upd_del(1, 1, N, y[fr], y[sc], {x[fr], sz(gr) }, 1);
        gr.pb({fr, sc});
    }
    else
    {
        if (mkr[fr][1]) return;
        mkr[fr][1] = 1;
        mkr[sc][1] = 1;
        if (x[fr] > x[sc]) swap(fr, sc);
        upd_del(1, 1, N, x[fr], x[sc], {y[fr], sz(gr) }, 0);
        gr.pb({fr, sc});
    }
}
int main()
{
    ios_base::sync_with_stdio(0); istream::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n;
    for (int i = 1; i < N; i++) xr[i] = yr[i] = -1;
    for (int i = 0; i < n; i++) {cin >> x[i] >> y[i]; a[i][0] = a[i][1] = -1;}
    for (int i = 0; i < n; i++)
        {
            int X = x[i], Y = y[i];
            if (xr[X] == -1) xr[X] = i; else {a[i][0] = xr[X]; a[xr[X]][0] = i;}
            if (yr[Y] == -1) yr[Y] = i; else {a[i][1] = yr[Y]; a[yr[Y]][1] = i;}
        }
    for (int i = 0; i < n; i++)
    {
        if (a[i][0] == a[i][1] && a[i][1] == -1) {cout << "NE" << endl; exit(0);}
        if (a[i][0] == -1 || a[i][1] == -1) alone.push(i); else {add_del(i, a[i][0]); add_del(i, a[i][1]);}
    }
    fnd();
    if (sz(g) != n / 2) {cout << "NE" << endl; exit(0);}
    cout << "DA" << endl;
    for (auto it : g) cout << it.F + 1 << " " << it.S + 1 << endl;
}
