QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#872724 | #8613. Cardinality | ucup-team3099# | ML | 605ms | 269036kb | C++23 | 5.6kb | 2025-01-26 03:57:54 | 2025-01-26 03:58:05 |
Judging History
answer
#include <iostream>
#include <vector>
#include <chrono>
#include <random>
#include <cassert>
struct TabulationHash {
uint64_t table[8][16];
void init(int seed) {
std::mt19937 rng(seed);
std::uniform_int_distribution<int> dist(0, 1);
for(int i = 0; i < 8; i++) {
for(int j = 0; j < 16; j++) {
table[i][j] = 0;
for(int k = 0; k < 64; k++) {
table[i][j] = (table[i][j] << 1) | dist(rng);
}
}
}
}
uint64_t operator () (uint32_t x) const {
uint64_t ans = 0;
for(int i = 0; i < 8; i++) {
ans ^= table[i][x & 15];
x >>= 4;
}
return ans;
}
};
TabulationHash hash;
struct HyperLogLog {
int logk;
std::vector<uint8_t> M;
std::vector<int> F;
double alpha;
void unite(HyperLogLog &other) {
for(int i = 0; i < (int) F.size(); i++) {
F[i] = 0;
}
for(int i = 0; i < (int) M.size(); i++) {
M[i] = std::max(M[i], other.M[i]);
F[M[i]]++;
}
}
uint8_t rho(uint64_t val, int pot) {
uint8_t ans = 0;
while(pot >= 0 && (val & (1LL << pot)) == 0) {
ans++;
pot--;
}
return ans;
}
void init(double eps, double delta, int seed) {
logk = 10;
//std::cout << "logk is " << logk << '\n';
alpha = 0.7213 / (1 + 1.079 / (1 << logk));
hash.init(seed);
M.assign(1 << logk, 0);
F.assign(64 - logk + 2, 0);
F[0] = 1 << logk;
}
void update(uint32_t x) {
uint64_t v = hash(x);
int i = (int)(v & ((1 << logk) - 1));
v = v >> logk;
assert(0 <= M[i] && M[i] < (int) F.size());
F[M[i]]--;
M[i] = std::max(M[i], rho(v, 64 - logk));
assert(0 <= M[i] && M[i] < (int) F.size());
F[M[i]]++;
}
double query() {
double sum = 0;
int zeroes = F[0];
for(int i = 0; i < (int) F.size(); i++) {
sum += F[i] / (double)(1LL << i);
}
double estimate = alpha * M.size() * M.size() / sum;
if(estimate <= 2.5 * (1 << logk)) {
if(zeroes != 0) {
estimate = (1 << logk) * log((double) (1 << logk) / zeroes);
}
} else if(estimate > (1LL << 32) / 30.0) {
estimate = - (1LL << 32) * log(1 - estimate / (1LL << 32));
}
return estimate;
}
};
int main() {
std::ios_base::sync_with_stdio(false); std::cin.tie(NULL);
int n, q;
std::cin >> n >> q;
std::vector<HyperLogLog> hll;
HyperLogLog base;
base.init(1, 5e-6, 189273);
for(int i = 0; i < n; i++) {
auto cur = base;
cur.update(i);
hll.push_back(cur);
// std::cout << "for value " << i << " got " << hll[i].query() << '\n';
}
for(int i = 0; i < q; i++) {
int u, v;
std::cin >> u >> v;
auto got = hll[u-1];
got.unite(hll[v-1]);
hll.push_back(got);
// std::cout << (got.query() + 0.5) << ", " << hll[u-1].query() << ", " << hll[v-1].query() << '\n';
std::cout << (int) (got.query() + 0.5);
if(i % 50 == 49 || i+1 == q) {
std::cout << std::endl;
} else {
std::cout << '\n';
}
}
}
/*
NEVER FORGET TO:
Look at the problem's constraints before coding.
How to cheese cf:
Find a lower bound or upper bound for the problem. Have faith that it is the answer of the problem.
If it isn't the answer, have more faith or change to another bound god by looking for a better bound.
Trust guesses. Who has time to think? If people in div2 AC the problem it requires no proof since people don't prove things.
You must draw cases. Thinking gets you nowhere, so draw cases and reach illogical conclusions from them.
Sometimes drawing cases is bad because it takes too much time. Faster is to not think at all and just code a bruteforce solution.
This is called "law of small numbers". If something works for small numbers, surely it works for big numbers.
https://en.wikipedia.org/wiki/Faulty_generalization#Hasty_generalization don't mind the "faulty" part of it, in competitive programming mistakes are lightly punished
Don't think about them being right or not, cf is a battle of intuition only.
Be as stupid as possible in implementation. Trying to be smart is an easy way to get WA.
Think about 2x2 cases for matrix problems and hope that everything works for the general case.
Find a necessary condition and trust it to be sufficient. They're basically the same thing.
Heuristics might speed up your code. Forget about complexity, it's only about ACing and not proving that your solution is good.
For paths in a grid starting at (1, i) or something like that, assume that they never cross and do D&C
Consider doing problems in reverse order of queries/updates
For combinatorics problems, consider symmetry
For problems that are similar to past problems, think about the differences betweem it and the current problem.
Sometimes the difference makes no difference. Sometimes it does.
General strategy (MUST DO):
Try to solve the problem with more restricted constraints.
About testing:
Test n=1, a[i]=1, a[i]=n, etc. Basically, test low values. No need to test if pretests are strong, but if you get WA it's good.
This isn't a joke. Do it if you get stuck. It's shit practice in my opinion, but do it if you want AC.
*/
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3840kb
input:
4 5 1 2 2 3 5 6 6 7 4 7
output:
2 2 3 3 4
result:
ok
Test #2:
score: 0
Accepted
time: 0ms
memory: 3968kb
input:
10 100 9 2 9 10 5 1 6 6 13 14 3 4 3 8 8 4 16 5 14 2 8 13 14 9 6 17 15 11 24 7 24 20 1 26 14 27 6 18 14 14 15 11 14 25 8 11 7 30 3 11 12 3 6 19 29 36 30 9 38 6 2 28 12 40 33 25 20 42 17 30 23 1 34 41 41 36 7 18 39 45 32 4 30 21 46 26 12 39 42 42 46 48 31 54 16 37 42 4 27 34 10 35 11 12 1 35 51 23 17 ...
output:
2 2 2 1 3 2 2 2 3 2 3 2 3 5 6 5 5 5 3 1 5 6 3 2 3 3 4 6 2 6 5 6 7 7 3 4 6 7 3 4 7 4 7 3 6 8 6 4 6 6 4 3 4 9 3 2 6 10 7 7 6 9 7 5 7 9 3 7 5 7 7 3 8 6 2 7 6 7 6 6 7 8 6 8 7 3 2 7 6 4 6 9 3 6 5 7 5 10 9 8
result:
ok
Test #3:
score: 0
Accepted
time: 0ms
memory: 3968kb
input:
100 100 82 51 68 54 25 11 21 47 84 43 78 91 1 88 29 50 10 62 38 29 100 65 23 4 77 10 29 7 59 39 56 81 73 3 113 10 49 25 59 103 20 40 42 55 46 87 9 26 30 43 70 97 7 12 2 54 41 68 82 60 129 69 86 82 85 38 105 71 81 58 59 36 76 111 10 68 108 19 46 31 127 60 35 120 79 125 138 21 14 10 64 72 140 127 126 ...
output:
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 3 2 3 2 3 4 3 3 2 2 4 3 2 3 2 3 4 2 2 3 2 4 3 5 4 2 4 4 2 4 3 3 4 2 2 3 2 3 5 2 5 3 3 3 3 4 3 2 2 3 5 3 3 3 2 2 5 4 2 4 4 3 2 4
result:
ok
Test #4:
score: 0
Accepted
time: 2ms
memory: 6144kb
input:
1000 1000 89 983 726 406 473 684 779 306 5 585 185 774 484 220 988 291 857 606 783 143 238 193 187 68 342 227 833 183 645 453 714 271 717 845 811 608 601 1013 101 716 563 790 500 449 962 863 255 787 236 837 560 412 788 681 487 992 311 884 389 251 199 927 942 1013 760 829 794 763 323 37 380 773 520 9...
output:
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 3 3 2 2 2 2 2 2 2 2 2 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 3 2 2 2 3 2 2 2 2 2 2 2 2 2 2 4 3 2 2 4 2 2 2 2 3 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 3 3 2 2 3 ...
result:
ok
Test #5:
score: 0
Accepted
time: 30ms
memory: 17976kb
input:
1000 10000 609 422 750 225 479 328 513 581 935 302 164 982 913 807 716 785 888 102 867 698 397 957 743 229 35 252 222 697 614 421 442 266 748 44 698 740 556 746 748 637 259 372 752 867 503 605 483 380 586 608 977 584 603 335 347 202 514 622 343 167 700 845 370 673 597 499 314 38 647 976 784 644 721 ...
output:
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 3 3 2 2 2 3 2 3 2 2 2 2 2 2 2 2 2 3 2 2 3 3 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 3 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 4 2 ...
result:
ok
Test #6:
score: 0
Accepted
time: 313ms
memory: 137920kb
input:
1000 100000 359 877 601 2 857 749 72 386 503 918 74 209 504 14 653 714 168 192 993 870 342 822 540 854 495 452 996 651 1005 932 898 279 105 83 778 924 517 326 326 16 747 863 73 501 190 386 211 416 330 72 857 269 543 485 344 637 111 611 449 942 426 739 585 459 100 269 1025 249 763 945 834 432 492 148...
output:
2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 3 2 2 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 2 2 2 3 3 2 2 2 2 2 2 3 3 2 2 2 2 4 2 2 2 2 3 2 2 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 3 5 2 2 2 3 2 2 2 4 2 2 ...
result:
ok
Test #7:
score: 0
Accepted
time: 605ms
memory: 269036kb
input:
1000 200000 769 45 350 115 462 826 361 748 422 502 757 529 131 165 525 252 5 610 58 557 894 966 867 661 699 337 508 118 248 715 307 307 814 382 957 825 302 694 22 761 146 621 149 929 553 337 428 844 429 371 355 740 889 726 1017 938 31 269 906 259 173 45 852 442 41 87 179 284 866 1033 115 130 757 192...
output:
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 5 3 4 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 3 2 2 2 2 2 3 2 3 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 3 2 3 4 2 2 2 2 2 2 2 3 ...
result:
ok
Test #8:
score: -100
Memory Limit Exceeded
input:
1000 500000 24 935 982 976 490 112 293 703 499 131 922 786 572 620 322 364 508 616 333 817 664 297 581 82 257 726 95 310 119 28 208 523 86 518 866 919 777 618 314 979 640 663 377 898 713 187 64 78 725 243 883 113 868 514 546 816 945 529 749 724 300 243 282 41 625 398 376 572 63 420 91 995 715 757 12...
output:
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 3 2 2 2 2 2 2 2 2 2 2 4 2 2 2 2 2 2 2 2 2 2 2 2 2 4 3 2 2 2 2 3 4 2 3 2 2 2 2 2 3 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 2 2 3 2 3 2 5 2 2 3 2 3 2 2 2 3 2 2 3 2 2 2 2 2 2 2 ...