QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#344737 | #7749. A Simple MST Problem | Lain | TL | 312ms | 125640kb | C++23 | 4.9kb | 2024-03-05 03:18:35 | 2024-03-05 03:18:35 |
Judging History
answer
/* #pragma GCC optimize("Ofast") */
/* #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma") */
/* #pragma GCC optimize("unroll-loops") */
#include "bits/extc++.h"
using namespace std;
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
// Source: ecnerwala
// Templates for Policy Based Data Structures
struct splitmix64_hash {
static uint64_t splitmix64(uint64_t x) {
// http://xorshift.di.unimi.it/splitmix64.c
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM =
std::chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
using namespace __gnu_pbds;
template <typename K, typename V, typename Hash = splitmix64_hash>
using hash_map = gp_hash_table<K, V, Hash>;
template <typename K, typename Hash = splitmix64_hash>
using hash_set = hash_map<K, null_type, Hash>;
template <class T, class Compare = less<>>
using ordered_set =
tree<T, null_type, Compare, rb_tree_tag, tree_order_statistics_node_update>;
// Source: Me
// Tested on: ???
// Merge by size + path compression
struct DSU {
struct node {
int p; // parent
int s; // size
};
vector<node> nodes;
DSU(int n) {
nodes.resize(n);
for (int i = 0; i < n; i++) {
nodes[i].p = i;
nodes[i].s = 1;
}
}
node& operator[](int index) { return nodes[index]; }
int size(int v) { return nodes[find(v)].s; }
int find(int v) {
if (nodes[v].p == v) return v;
return nodes[v].p = find(nodes[v].p);
}
bool merge(int a, int b) {
a = find(a);
b = find(b);
if (a == b) return false;
if (nodes[a].s < nodes[b].s) swap(a, b);
nodes[b].p = a;
nodes[a].s += nodes[b].s;
return true;
}
vector<vector<int>> get_components() {
vector<vector<int>> g(nodes.size());
for (int i =0; i < nodes.size(); i++)
g[find(i)].push_back(i);
g.erase(remove_if(g.begin(), g.end(), [&](vector<int>& v)->bool {
return v.empty();
}), g.end());
return g;
}
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
const int N = 1e6+7;
vector<vector<int>> prime_facs(N);
for (int i = 2; i < N; i++) {
if (prime_facs[i].empty()) {
for (int j = i; j < N; j += i) {
prime_facs[j].push_back(i);
}
}
}
vector<vector<vi>> buckets(N);
vector<int> curr_idx(N, -1);
vector<int> min_idx(N, -1);
int tt;
cin >> tt;
while(tt--) {
const int MAX_W = 15;
vector<queue<int>> pq(MAX_W);
int merges = 0;
int l, r;
cin >> l >> r;
r++;
set<int> touched;
DSU d(r-l);
int64_t ans = 0;
rep(x, l, r) {
bool ok = sz(prime_facs[x]);
for (auto& p : prime_facs[x]) {
if (x/p < l) {
ok = false;
break;
}
}
if (ok) {
merges++;
d.merge(x-l, x/prime_facs[x][0]-l);
ans += sz(prime_facs[x]);
continue;
}
for (int mask = 0; mask < 1<<sz(prime_facs[x]); mask++) {
int y = 1;
rep(i, 0, sz(prime_facs[x])) {
if (mask>>i&1)
y *= prime_facs[x][i];
}
touched.insert(y);
buckets[y].resize(8);
// this is the difference from x to the base
int diff = sz(prime_facs[x]) - __builtin_popcount(mask);
buckets[y][diff].push_back(x);
}
}
for (auto& x : touched) {
for (int i = 0; i < 8; i++) {
if (sz(buckets[x][i])) {
if (min_idx[x] == -1) {
min_idx[x] = i;
if (sz(buckets[x][i]) != 1) {
curr_idx[x] = i;
break;
}
} else {
curr_idx[x] = i;
break;
}
}
}
if (min_idx[x] == -1 || curr_idx[x] == -1) continue;
pq[sz(prime_facs[x]) + min_idx[x] + curr_idx[x]].emplace(x);
}
int currw = 0;
while(merges != r-l - 1){
while(pq[currw].empty()) currw++;
auto x = pq[currw].front();
pq[currw].pop();
for (auto& v : buckets[x][curr_idx[x]]) {
if(d.merge(v-l, buckets[x][min_idx[x]][0] - l)) {
merges++;
ans += currw;
}
}
curr_idx[x]++;
while(curr_idx[x] < sz(buckets[x]) && buckets[x][curr_idx[x]].empty())
curr_idx[x]++;
if (curr_idx[x] != sz(buckets[x])) {
pq[sz(prime_facs[x]) + min_idx[x] + curr_idx[x]].emplace(x);
}
}
cout << ans << '\n';
for (auto& y : touched) {
buckets[y].clear();
min_idx[y] = -1;
curr_idx[y] = -1;
}
}
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 162ms
memory: 90020kb
input:
5 1 1 4 5 1 4 1 9 19 810
output:
0 2 3 9 1812
result:
ok 5 lines
Test #2:
score: 0
Accepted
time: 301ms
memory: 125640kb
input:
2 27 30 183704 252609
output:
8 223092
result:
ok 2 lines
Test #3:
score: 0
Accepted
time: 312ms
memory: 125640kb
input:
1 183704 252609
output:
223092
result:
ok single line: '223092'
Test #4:
score: -100
Time Limit Exceeded
input:
2 639898 942309 30927 34660
output:
983228 11512