Submission #640225

#TimeUsernameProblemLanguageResultExecution timeMemory
640225colazcyMatching (COCI20_matching)C++17
110 / 110
2354 ms84364 KiB
#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <vector>
#include <set>
#include <algorithm>
#include <queue>
#include <utility>
#define let const auto
#define rep(name,beg,end) for(auto lim_##name = end,name = beg;name <= lim_##name;name++)
#define per(name,beg,end) for(auto lim_##name = end,name = beg;name >= lim_##name;name--)
#define repn(lim) for(auto REPN_lIM = lim,REPN = 1;REPN <= REPN_lIM;REPN++)
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define trace() debug("line : %d, Function : %s\n",__LINE__,__FUNCTION__)
using ci = const int;
constexpr int maxn = 1e5 + 100;

struct Seg{
    #define ls (x << 1)
    #define rs (x << 1 | 1)
    static const int M = 100000;
    std::set<int> s[maxn << 2];
    void ins(ci a,ci b,ci v,ci l = 1,ci r = M,ci x = 1){
        if(a <= l && b >= r){
            s[x].insert(v);
            return;
        }
        let mid = (l + r) >> 1;
        if(a <= mid)ins(a,b,v,l,mid,ls);
        if(b > mid)ins(a,b,v,mid + 1,r,rs);
    }
    bool query(ci p,ci a,ci b,ci l = 1,ci r = M,ci x = 1){
        let it = s[x].lower_bound(a);
        if(it != s[x].end() && *it <= b)return true;
        if(l == r)return false;
        let mid = (l + r) >> 1;
        if(p <= mid)return query(p,a,b,l,mid,ls);
        return query(p,a,b,mid + 1,r,rs);
    }
    #undef ls
    #undef rs
};

struct Point{
    int x,y;
}p[maxn];
int n;
std::vector<std::pair<int,int>> ans;

[[noreturn]] void nosol(){
    std::puts("NE");
    std::exit(0);
}

bool vis[maxn];
Seg seg_row,seg_col;
void match(ci a,ci b){
    if(p[a].x == p[b].x){
        let l = std::min(p[a].y,p[b].y);
        let r = std::max(p[a].y,p[b].y);
        if(seg_row.query(p[a].x,l,r))nosol();
        seg_col.ins(l,r,p[a].x);
    }
    if(p[a].y == p[b].y){
        let l = std::min(p[a].x,p[b].x);
        let r = std::max(p[a].x,p[b].x);
        if(seg_col.query(p[a].y,l,r))nosol();
        seg_row.ins(l,r,p[a].y);
    }
    vis[a] = vis[b] = 1;
    ans.emplace_back(a,b);
}
bool chk(ci a,ci b){
    if(p[a].x == p[b].x){
        let l = std::min(p[a].y,p[b].y);
        let r = std::max(p[a].y,p[b].y);
        if(seg_row.query(p[a].x,l,r))return false;
    }
    if(p[a].y == p[b].y){
        let l = std::min(p[a].x,p[b].x);
        let r = std::max(p[a].x,p[b].x);
        if(seg_col.query(p[a].y,l,r))return false;
    }
    return true;
}

struct Rect{
    int a,b,c,d;
};

std::vector<Rect> rect;
std::vector<int> row[maxn],col[maxn];

std::vector<int> G[maxn];
int deg[maxn];
void addedge(ci u,ci v){
    G[u].push_back(v);
    G[v].push_back(u);
    deg[u]++;
    deg[v]++;
}
void topo(){
    std::queue<int> q;
    rep(i,1,n)
        if(!deg[i])nosol();
    rep(i,1,n)
        if(deg[i] == 1)q.push(i);
    while(!q.empty()){
        let u = q.front(); q.pop();
        for(let v : G[u]){
            if(vis[v])continue;
            if(!vis[u])match(u,v);
            if(--deg[v] == 1)q.push(v);
        }
    }
}

std::vector<int> stk;
void dfs(const int u){
    if(vis[u])return;
    vis[u] = 1;
    stk.push_back(u);
    for(let v : G[u])dfs(v);
}
std::vector<std::pair<std::vector<std::pair<int,int>>,std::vector<std::pair<int,int>>>> fuck;

int main(){
    std::scanf("%d",&n);
    rep(i,1,n)std::scanf("%d %d",&p[i].x,&p[i].y);
    rep(i,1,n)
        row[p[i].y].push_back(i),
        col[p[i].x].push_back(i);
    rep(i,0,maxn - 1)
        if(row[i].size() == 2)
            addedge(row[i].front(),row[i].back());
    rep(i,0,maxn - 1)
        if(col[i].size() == 2)
            addedge(col[i].front(),col[i].back());
    topo();
    rep(i,1,n)
        if(!vis[i]){
            stk.clear();
            dfs(i);
            for(let s : stk)
                if(!deg[s])nosol();
            std::vector<std::pair<int,int>> A,B;
            A.reserve(stk.size() >> 1);
            B.reserve(stk.size() >> 1);
            for(size_t i = 1;i < stk.size();i += 2)A.emplace_back(stk[i - 1],stk[i]);

            for(size_t i = 2;i < stk.size();i += 2)B.emplace_back(stk[i - 1],stk[i]);
            B.emplace_back(stk.front(),stk.back());
            fuck.emplace_back(std::move(A),std::move(B));
        }

    std::set<int> s;
    for(size_t i = 0;i < fuck.size();i++)s.insert(i);
    while(!s.empty()){
        bool flg = false;
        for(auto it = s.begin();it != s.end();){
            let i = *it;
            let &pir = fuck[i];
            bool fA = true,fB = true;
            for(let &p : pir.first)
                if(!chk(p.first,p.second)){
                    fA = false;
                    break;
                }
            for(let &p : pir.second)
                if(!chk(p.first,p.second)){
                    fB = false;
                    break;
                }
            if(!fA && !fB)nosol();
            if(fA && fB){
                it++;
                continue;
            }
            flg = true;
            if(fA)
                for(let &p : pir.first)match(p.first,p.second);
            if(fB)
                for(let &p : pir.second)match(p.first,p.second);
            it = s.erase(it);
        }
            
        if(!flg){
            let it = s.begin();
            let i = *it;
            let &pir = fuck[i];
            for(let &p : pir.first)match(p.first,p.second);
            s.erase(it);
        }
    }
    std::puts("DA");
    for(let &pir : ans)std::printf("%d %d\n",pir.first,pir.second);
    assert(ans.size() == n / 2);
    return 0;
}

Compilation message (stderr)

In file included from /usr/include/c++/10/cassert:44,
                 from matching.cpp:2:
matching.cpp: In function 'int main()':
matching.cpp:197:23: warning: comparison of integer expressions of different signedness: 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  197 |     assert(ans.size() == n / 2);
      |            ~~~~~~~~~~~^~~~~~~~
matching.cpp:128:15: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  128 |     std::scanf("%d",&n);
      |     ~~~~~~~~~~^~~~~~~~~
matching.cpp:129:25: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  129 |     rep(i,1,n)std::scanf("%d %d",&p[i].x,&p[i].y);
      |               ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#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...