Submission #405648

#TimeUsernameProblemLanguageResultExecution timeMemory
405648rqiCircle selection (APIO18_circle_selection)C++14
100 / 100
1947 ms383952 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef vector<int> vi; typedef pair<int, int> pi; typedef pair<ll, ll> pl; typedef vector<pl> vpl; typedef double db; #define f first #define s second #define pb push_back #define mp make_pair #define sz(x) (int)(x).size() #define all(x) begin(x), end(x) mt19937 rng(127); const int SZ = 100; #include <ext/pb_ds/assoc_container.hpp> using namespace __gnu_pbds; const uint64_t C = ll(2e18*3.1415926535)+71; // large odd number const int RANDOM = rng(); // random 32-bit number ll hashNum(ll x) { // https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html return __builtin_bswap64((x^RANDOM)*C); } struct hashFunc{ ll operator()(const pl& a) const { return hashNum(a.f)^(hashNum(a.s)+1); } }; const int mx = 300005; int n; ll x[mx]; ll y[mx]; ll r[mx]; bool circIntersect(int a, int b){ ll dist_sq = (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]); if(dist_sq <= (r[a]+r[b])*(r[a]+r[b])){ return true; } return false; } vector<pair<ll, int>> buckets[35]; int ans[mx]; gp_hash_table<pl, vi, hashFunc> g; ll GRID; ll fdiv(ll a, ll b){ assert(b >= 1); if(a >= 0) return a/b; return (a+1)/b-1; } pl gridReduce(pl a){ return mp(fdiv(a.f, GRID), fdiv(a.s, GRID)); } void remDup(vpl& a){ sort(all(a)); a.erase(unique(all(a)), a.end()); } vpl getCorners(int circ){ vpl corners = vpl{mp(x[circ]+r[circ], y[circ]+r[circ]), mp(x[circ]-r[circ], y[circ]+r[circ]), mp(x[circ]-r[circ], y[circ]-r[circ]), mp(x[circ]+r[circ], y[circ]-r[circ])}; vector<pl> res; for(auto u: corners){ res.pb(gridReduce(u)); } remDup(res); return res; } int main(){ cin.tie(0)->sync_with_stdio(0); cin >> n; // n = 300000; // clock_t c = clock(); // cout << fixed << setprecision(6); for(int i = 1; i <= n; i++){ cin >> x[i] >> y[i] >> r[i]; // x[i] = rng() % SZ - SZ/2; // y[i] = rng() % SZ - SZ/2; // r[i] = 1 + rng() % SZ; } for(int i = 1; i <= n; i++){ for(int j = 0; j < 35; j++){ if(r[i] < (1LL<<j)){ buckets[j-1].pb(mp(-r[i], i)); break; } } } assert(sz(buckets[30]) == 0); //cout << db(clock()-c)/db(CLOCKS_PER_SEC) << "\n"; int num = 0; for(int k = 29; k >= 0; k--){ sort(all(buckets[k])); if(sz(buckets[k]) == 0) continue; g.clear(); GRID = (1LL<<(k+2)); for(int i = 1; i <= n; i++){ if(ans[i] == 0){ for(auto u: getCorners(i)){ g[u].pb(i); num++; } } } for(auto circ: buckets[k]){ int ind = circ.s; if(ans[ind] == 0){ for(auto u: getCorners(ind)){ vi new_cands; for(auto cand: g[u]){ //num++; if(ans[cand] != 0) continue; if(circIntersect(ind, cand)){ ans[cand] = ind; } else{ new_cands.pb(cand); } } g[u] = new_cands; } assert(ans[ind] == ind); } } } // cout << num << "\n"; // cout << db(clock()-c)/db(CLOCKS_PER_SEC) << "\n"; for(int i = 1; i <= n; i++){ cout << ans[i] << " "; } cout << "\n"; // cout << db(clock()-c)/db(CLOCKS_PER_SEC) << "\n"; }
#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...