제출 #658352

#제출 시각아이디문제언어결과실행 시간메모리
658352hugo_pm원 고르기 (APIO18_circle_selection)C++17
100 / 100
1674 ms609972 KiB
#include <iostream>
#include <unordered_map>
#include <algorithm>
#include <vector>
#include <time.h>
#include <chrono>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
    
struct uint64_hash {
    static inline uint64_t rotr(uint64_t x, unsigned k) {
    return (x >> k) | (x << (8U * sizeof(uint64_t) - k));
    }
    
    static inline uint64_t hash_int(uint64_t x) noexcept {
    auto h1 = x * (uint64_t)(0xA24BAED4963EE407);
    auto h2 = rotr(x, 32U) * (uint64_t)(0x9FB21C651E98DF25);
    auto h = rotr(h1 + h2, 32U);
    return h;
    }
    
    size_t operator()(uint64_t x) const {
    static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count();
    return hash_int(x + FIXED_RANDOM);
    }
};
    
template <typename K, typename V, typename Hash = uint64_hash>
using hash_map = __gnu_pbds::gp_hash_table<K, V, Hash>;
template <typename K, typename Hash = uint64_hash>
using hash_set = hash_map<K, __gnu_pbds::null_type, Hash>;
template <typename T>
using ordered_set = __gnu_pbds::tree<T, __gnu_pbds::null_type, std::less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
    
using namespace std;
    
const int MAX_CERCLE = 3e5+42, INF = 1e9;
    
struct Cercle{
    long long xCentre, yCentre, rayon, id;
    
    bool operator<(Cercle autre) {
        if(rayon == autre.rayon)
            return id < autre.id;
        return rayon > autre.rayon;
    }
};
    
int nbCercle;
Cercle cercle[MAX_CERCLE];
    
void input() {
    cin >> nbCercle;
    
    for(int idCercle = 0; idCercle < nbCercle; idCercle++) {
        cin >> cercle[idCercle].xCentre >> cercle[idCercle].yCentre >> cercle[idCercle].rayon;
        cercle[idCercle].xCentre += INF;
        cercle[idCercle].yCentre += INF;
        cercle[idCercle].id = idCercle;
    }
    sort(cercle, cercle + nbCercle);
}

// simulate hash_map<K, stack<V>>
template<typename K, typename V>
struct map2d {
    hash_map<K, int> to_last;
    vector<V> content;
    vector<int> prev;
    map2d() { clear(); }

    void push(K key, V value) {
        int location = content.size();
        content.push_back(value);
        prev.push_back(to_last[key]);
        to_last[key] = location;
    }
    
    bool pop(K key, V& popped) {
        int location = to_last[key];
        if (!location) return false;
        popped = content[location];
        to_last[key] = prev[location];
        return true;
    }

    bool empty(K key) {
        return to_last[key] == 0;
    }
    void erase(K key) {
        to_last[key] = 0;
    }
    void clear() {
        to_last.clear();
        content.resize(1);
        prev.resize(1);
    }
};
map2d<long long, int> grille;
bool enleve[MAX_CERCLE] = {0};
    
int quiEnleve[MAX_CERCLE];
    
long long tailleGrille = (1e12);
    
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    input();
    
    for(int grand = 0; grand < nbCercle; grand++) {
        if(enleve[grand])
            continue;
    
        bool change = 0;
        while(tailleGrille/2 > cercle[grand].rayon) {
            tailleGrille /= 2;
            change = 1;
        }
    
        if(change) {
            grille.clear();
            for(int cur = 0; cur < nbCercle; cur++) {
                if(enleve[cur])
                    continue;
                long long xGrille = cercle[cur].xCentre / tailleGrille, yGrille = cercle[cur].yCentre / tailleGrille;
                
                grille.push((xGrille << 32) + yGrille, cur);
            }
        }
    
        long long xGrille = cercle[grand].xCentre / tailleGrille, yGrille = cercle[grand].yCentre / tailleGrille;
    
        vector<int> quiReste;
        for(int type = 0; type < 2; type++) {
            for(int deltaX = -2; deltaX <= 2; deltaX++) {
                for(int deltaY = -2; deltaY <= 2; deltaY++) {
                    long long nouvX = xGrille + deltaX, nouvY = yGrille + deltaY;
    
                    if(type == 1) {
                        grille.erase((nouvX << 32) + nouvY);
                        continue;
                    }

                    int autre;
                    while (grille.pop((nouvX << 32) + nouvY, autre)) {
                        long long xDist = cercle[grand].xCentre - cercle[autre].xCentre, yDist = cercle[grand].yCentre - cercle[autre].yCentre;
                        long long rDist = cercle[grand].rayon + cercle[autre].rayon;
    
                        if(xDist * xDist + yDist * yDist <= rDist * rDist && !enleve[autre]) {
                            enleve[autre] = 1;
                            quiEnleve[cercle[autre].id] = cercle[grand].id;
                        }
                        if(xDist * xDist + yDist * yDist > rDist * rDist) {
                            quiReste.push_back(autre);
                        }
                    }
                }
            }
        }
    
        for(auto nouveau : quiReste) {
            if(enleve[nouveau])
                continue;
            long long xGrille = cercle[nouveau].xCentre / tailleGrille, yGrille = cercle[nouveau].yCentre / tailleGrille;
            
            grille.push((xGrille << 32) + yGrille, nouveau);
        }
    }
    
    for(int cur = 0; cur < nbCercle; cur++) {
        cout << quiEnleve[cur]+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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...