제출 #1321174

#제출 시각아이디문제언어결과실행 시간메모리
1321174SmuggingSpun분수 공원 (IOI21_parks)C++20
100 / 100
385 ms36012 KiB
#include "parks.h"
#include<bits/stdc++.h>
using namespace std;
vector<int>x, y;
int n;
namespace sub1{
  int solve(){
    vector<int>p(n);
    iota(p.begin(), p.end(), 0);
    sort(p.begin(), p.end(), [&] (int i, int j){
      return y[i] < y[j];
    });
    vector<int>u, v, a, b;
    for(int i = 1; i < n; i++){
      if(y[p[i]] > y[p[i - 1]] + 2){
        return 0;
      }
      u.push_back(p[i - 1]);
      v.push_back(p[i]);
      a.push_back(1);
      b.push_back(y[p[i]] - 1);
    }
    build(u, v, a, b);
    return 1;
  }
}
namespace sub2{
  int solve(){
    vector<map<int, int>>id(2);
    for(int i = 0; i < n; i++){
      id[(x[i] - 1) >> 1][y[i]] = i;
    }  
    vector<pair<int, int>>edge;
    auto create_edge = [&] (int i, int x, int y){
      if(x == 0){
        return;
      }
      auto it = id[x = (x - 1) >> 1].find(y);
      if(it != id[x].end()){
        edge.push_back(make_pair(i, it->second));
      }
    };
    for(int i = 0; i < n; i++){
      create_edge(i, x[i] - 2, y[i]);
      create_edge(i, x[i], y[i] - 2);
    }
    vector<int>lab(n);
    iota(lab.begin(), lab.end(), 0);
    auto find_set = [&] (int i){
      while(i != lab[i]){
        i = lab[i] = lab[lab[i]];
      }
      return i;
    };
    function<bool(int, int)>merge = [&] (int i, int j){
      if((i = find_set(i)) != (j = find_set(j))){
        lab[i] = j;
        return true;
      }
      return false;
    };
    vector<int>u, v, a, b;
    for(auto& [i, j] : edge){
      if(merge(i, j)){
        u.push_back(i);
        v.push_back(j);
        if(x[i] == x[j]){
          a.push_back(x[i] == 2 ? 1 : 5);
          b.push_back(max(y[i], y[j]) - 1);
        }
        else{
          a.push_back(3);
          b.push_back(y[i] - 1);
        }
      }
    }
    if(u.size() != n - 1){
      return 0;
    }
    build(u, v, a, b);
    return 1;
  }
}
namespace sub3{
  int solve(){
    vector<map<int, int>>id(3);
    for(int i = 0; i < n; i++){
      id[(x[i] - 1) >> 1][y[i]] = i;
    }  
    vector<pair<int, int>>edge;
    auto create_edge = [&] (int i, int x, int y){
      if(x == 0){
        return;
      }
      auto it = id[x = (x - 1) >> 1].find(y);
      if(it != id[x].end()){
        edge.push_back(make_pair(i, it->second));
      }
    };
    for(int i = 0; i < n; i++){
      create_edge(i, x[i] - 2, y[i]);
      create_edge(i, x[i], y[i] - 2);
    }
    vector<int>lab(n);
    iota(lab.begin(), lab.end(), 0);
    auto find_set = [&] (int i){
      while(i != lab[i]){
        i = lab[i] = lab[lab[i]];
      }
      return i;
    };
    function<bool(int, int)>merge = [&] (int i, int j){
      if((i = find_set(i)) != (j = find_set(j))){
        lab[i] = j;
        return true;
      }
      return false;
    };
    vector<int>u, v, a, b;
    sort(edge.begin(), edge.end(), [&] (pair<int, int>i, pair<int, int>j){
      return min(make_pair(x[i.first], y[i.first]), make_pair(x[i.second], y[i.second])) < min(make_pair(x[j.first], y[j.first]), make_pair(x[j.second], y[j.second]));
    });
    map<pair<int, int>, bool>vis;
    for(auto& [i, j] : edge){
      if(merge(i, j)){
        u.push_back(i);
        v.push_back(j);
        if(x[i] == x[j]){
          if(x[i] == 2 || x[i] == 6){
            a.push_back(x[i] == 2 ? 1 : 7);
          }
          else if(!vis[make_pair(3, max(y[i], y[j]) - 1)]){
            vis[make_pair(3, max(y[i], y[j]) - 1)] = true;
            a.push_back(3);
          }
          else{
            vis[make_pair(5, max(y[i], y[j]) - 1)] = true;
            a.push_back(5);
          }
          b.push_back(max(y[i], y[j]) - 1);
        }
        else{
          int X = max(x[i], x[j]) - 1;
          a.push_back(X);
          if(!vis[make_pair(X, y[i] - 1)]){
            vis[make_pair(X, y[i] - 1)] = true;
            b.push_back(y[i] - 1);
          }
          else{
            vis[make_pair(X, y[i] + 1)] = true;
            b.push_back(y[i] + 1);
          }
        }
      }
    }
    if(u.size() != n - 1){
      return 0;
    }
    build(u, v, a, b);
    return 1;
  }
}
namespace sub456{
  int solve(){
    vector<int>lab(n);
    iota(lab.begin(), lab.end(), 0);
    auto find_set = [&] (int i){
      while(i != lab[i]){
        i = lab[i] = lab[lab[i]];
      }
      return i;
    };
    function<bool(int, int)>merge = [&] (int i, int j){
      if((i = find_set(i)) != (j = find_set(j))){
        lab[i] = j;
        return true;
      }
      return false;
    };
    vector<int>p(n);
    iota(p.begin(), p.end(), 0);
    sort(p.begin(), p.end(), [&] (int i, int j){
      return x[i] < x[j] || (x[i] == x[j] && y[i] < y[j]);
    });
    map<pair<int, int>, int>id;
    for(int i = 0; i < n; i++){
      id[make_pair(x[i], y[i])] = i;
    }
    vector<int>u, v, a, b;
    for(int& i : p){
      auto it = id.find(make_pair(x[i], y[i] + 2));
      if(it != id.end()){
        int p = it->second;
        if(merge(i, p)){
          if(~((x[i] >> 1) + (y[i] >> 1)) & 1){
            a.push_back(x[i] - 1);
          }
          else{
            a.push_back(x[i] + 1);
          }
          b.push_back(y[i] + 1);
          u.push_back(i);
          v.push_back(p);
        }
      }
      if((it = id.find(make_pair(x[i] + 2, y[i]))) != id.end()){
        int p = it->second;
        if(find_set(i) != find_set(p)){
          if(((x[i] >> 1) + (y[i] >> 1)) & 1){
            if(id.find(make_pair(x[i], y[i] - 2)) != id.end() && id.find(make_pair(x[i] + 2, y[i] - 2)) != id.end()){
              continue;
            }
            b.push_back(y[i] - 1);
          }
          else{
            b.push_back(y[i] + 1);
          }
          a.push_back(x[i] + 1);
          u.push_back(i);
          v.push_back(p);
          merge(i, p);
        }
      }
    }
    if(u.size() != n - 1){
      return 0;
    }
    build(u, v, a, b);
    return 1;
  }
}
int construct_roads(vector<int>_x, vector<int>_y){
  swap(x, _x);
  swap(y, _y);
  n = x.size();
  if(*max_element(x.begin(), x.end()) == 2){
    return sub1::solve();
  }
  if(*max_element(x.begin(), x.end()) <= 4){
    return sub2::solve();
  }
  if(*max_element(x.begin(), x.end()) <= 6){
    return sub3::solve();
  }
  return sub456::solve();
}
#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...