#include "triples.h"
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
using vi = vector<int>;
using vvi = vector<vi>;
using vl = vector<ll>;
using vvl = vector<vl>;
using pi = pair<int, int>;
#define FOR(i, a, b) for (int i = a; i < b; i++)
#define ROF(i, a, b) for (int i = a; i >= b; i--)
#define each(a, x) for (auto &a : x)
#define all(x) (x).begin(), (x).end()
#define bg(x) (x).begin()
#define en(x) (x).end()
#define rev(x) reverse(all(x))
#define sz(x) int((x).size())
#define srt(x) sort(all(x))
#define cnt(a, x) count(all(x), a)
#define trace(x) each(a, (x)) cout << a << " "
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound
ll brute(vi h) {
int n = sz(h);
ll ans = 0;
FOR(i, 0, n) {
FOR(j, i+1, n) {
FOR(k, j+1, n) {
int d1 = min({k-j, k-i,j-i}), d3 = max({k-j, j-i, k-i}), f1 = min({h[i], h[j], h[k]}), f3 = max({h[i], h[j], h[k]});
int d2 = (k-j) ^ (k-i) ^ (j-i) ^ d1 ^ d3, f2 = h[i] ^ h[j] ^ h[k] ^ f1 ^ f3;
if (d1 == f1 && d2 == f2 && d3 == f3) ans++;
}
}
}
return ans;
}
struct Triple {
int i, j, k;
Triple() {};
Triple(int I, int J, int K) {
i = min({I, J, K});
k = max({I, J, K});
j = (I ^ J ^ K) ^ i ^ k; // lol
}
const bool operator<(const Triple &other) const {
if (i != other.i) return i < other.i;
if (j != other.j) return j < other.j;
return k < other.k;
}
};
ll count_triples(vi h) {
int n = sz(h);
ll ans = 0;
FOR(i, 0, n) { // count number of triples where h[i] = d(i, j) or d(i, k)
int H = h[i];
set<Triple> trips; // prevent double count with dupe height
int j = i + H;
if (j < n) {
int k1 = i + h[j], k2 = j + h[j]; // 2 cases — h[j] = d(i, k) or h[j] = d(j, k)
if (k1 < n && h[k1] == (k1 - j)) trips.insert(Triple(i, j, k1)); // we know d(i, j) and d(i, k) to be h[i] and h[j], so does h[k] == d(j, k)
if (k2 < n && h[k2] == (k2 - i)) trips.insert(Triple(i, j, k2)); // symmetric but this time for i
}
int k = i + H;
if (k < n) {
int j1 = i + h[k], j2 = k - h[k]; // h[k] = d(i, k), h[k] = d(j, k)
if ((i < j1 && j1 < k) && h[j1] == (k - j1)) trips.insert(Triple(i, j1, k));
if ((i < j2 && j2 < k) && h[j2] == (j2 - i)) trips.insert(Triple(i, j2, k));
}
for (auto &el : trips) {
if (h[el.j] != h[el.i] && h[el.k] != h[el.i]) ans++;
}
}
unordered_map<int, vector<int>> pc, nc; // positive line intercepts, negative line intercepts
vi inp(n), inn(n); // lookup for the intercept
FOR(i, 0, n) {
int c1 = h[i] - i, c2 = h[i] + i;
inp[i] = c1, inn[i] = c2;
pc[c1].pb(i), nc[c2].pb(i);
}
for (auto &cnst : pc) { // count number of triples where h[j] = d(i, j), h[k] = d(i, k), and h[i] = d(j, k) = h[k] - h[j]
int i = -cnst.first;
if (i < 0 || i >= n) continue;
int H = h[i];
for (auto &el : cnst.second) {
int j = el, k = el + H;
if (k >= n) break;
if (inp[k] != inp[j]) continue;
ans++;
}
}
FOR(j, 0, n) { // count number of triples where h[j] = d(i, k), h[k] = d(i, j) and h[i] = d(j, k) = h[j] - h[k]
int f1 = lower_bound(all(pc[inp[j]]), j-h[j]) - bg(pc[inp[j]]);
int f2 = upper_bound(all(nc[inn[j]]), j+h[j]) - bg(nc[inn[j]]);
int p1 = lower_bound(all(pc[inp[j]]), j) - bg(pc[inp[j]]), p2 = lower_bound(all(nc[inn[j]]), j) - bg(nc[inn[j]]);
if (p1 - f1 < f2 - p2) { // there is no way to set up the diagonals such that no matter which way you go its n^2
for (int el = f1; el < p1; el++) {
int i = pc[inp[j]][el];
int dist = j - i;
if (j + h[i] >= n || h[j + h[i]] != dist) continue;
ans++;
}
} else {
for (int el = p2 + 1; el < f2; el++) {
int k = nc[inn[j]][el];
int dist = k - j;
if (j - h[k] < 0 || h[j - h[k]] != dist) continue;
ans++;
}
}
}
return ans;
}
bool accept(double cur_score, double next_score, double temp, mt19937 &rng) {
if (next_score > cur_score) return true;
cur_score = -cur_score; next_score = -next_score;
double prob = exp(-(next_score - cur_score) / temp);
return generate_canonical<double, 53>(rng) < prob;
}
vi construct_range(int M, int K) {
vi cur = {3, 1, 2, 1, 4, 5, 4, 3, 8, 7, 6, 9, 12, 3, 10, 5, 1, 7, 14, 9, 4, 11, 18, 23, 8, 15, 26, 23, 24, 25, 20, 21, 22, 17, 18, 19, 4, 13, 14, 15, 1, 9, 10, 11, 40, 5, 6, 7, 38, 3, 4, 1, 2, 1, 3, 15, 6, 25, 26, 27, 10, 21, 22, 23, 14, 25, 16, 17, 18, 15, 16, 21, 18, 19, 4, 1, 6, 7, 8, 5, 2, 3, 4, 1, 2, 1, 4, 3, 2, 3, 1, 1, 2, 4, 3, 6, 5, 6, 7, 2, 3, 4, 1, 2, 1, 8, 3, 6, 5, 4, 21, 20, 21, 15, 17, 18, 15, 16, 13, 14, 11, 12, 25, 10, 23, 22, 21, 22, 19, 40, 39, 40, 1, 36, 37, 34, 35, 32, 33, 48, 7, 40, 45, 38, 43, 42, 41, 34, 57, 58, 19, 18, 19, 52, 51, 50, 25, 24, 11, 28, 27, 60, 15, 58, 17, 16, 15, 20, 37, 36, 1, 80, 75, 4, 73, 6, 75, 86, 9, 8, 83, 9, 81, 80, 3, 36, 77, 18, 17, 58, 57, 60, 59, 12, 93, 26, 9, 66, 65, 108, 109, 100, 105, 106, 103, 104, 101, 102, 39, 38, 41, 40, 81, 122, 33, 110, 47, 30, 117, 32, 89, 88, 41, 92, 91, 38, 21, 80, 23, 58, 99, 62, 61, 102, 29, 66, 65, 50, 69, 70, 69, 60, 73, 72, 57, 64, 41, 60, 61, 2, 69, 64, 83, 48, 83, 8, 51, 52, 77, 78, 55, 74, 75, 3, 43, 60, 35, 20, 47, 18, 65, 66, 21, 52, 27, 12, 25, 30, 31, 28, 29, 34, 19, 32, 53, 22, 23, 8, 37, 26, 3, 44, 45, 42, 7, 8, 33, 10, 11, 36, 37, 8, 1, 16, 3, 4, 19, 52, 1, 16, 9, 24, 3, 12, 21, 22, 9, 8, 17, 18, 5, 14, 13, 14, 6, 10, 11, 8, 4, 5, 5, 6, 3, 1, 10, 11, 1, 8, 14, 7, 6, 17, 10, 9, 8, 13, 12, 23, 4, 3, 26, 19, 6, 7, 22, 3, 32, 13, 12, 55, 28, 27, 58, 31, 40, 5, 22, 21, 36, 35, 18, 37, 48, 15, 30, 29, 44, 43, 26, 9, 56, 23, 38, 37, 52, 51, 34, 17, 64, 31, 46, 45, 60, 59, 70, 25, 8, 73, 66, 65, 76, 69, 68, 33, 16, 59, 82, 83, 62, 85, 78, 79, 8, 81, 80, 83, 82, 71, 72, 75, 74, 69, 76, 71, 66, 73, 38, 67, 8, 41, 60, 43, 62, 29, 30, 65, 16, 33, 50, 51, 36, 53, 22, 55, 8, 25, 42, 43, 28, 45, 14, 47, 48, 17, 34, 35, 20, 37, 6, 39, 40, 9, 26, 27, 12, 29, 4, 3, 32, 5, 6, 19, 2, 3, 14, 23, 12, 13, 16, 15, 10, 17, 12, 7, 14, 9, 12, 11, 12, 1, 8, 3, 2, 5, 4, 5, 2, 3, 6, 1};
vi ret;
while (ret.size() < M) {
for (auto &el : cur) {
ret.pb(el);
if (ret.size() >= M) break;
}
}
return ret;
// vi cur(M, 1), best(M, 1);
// int score = 0, best_score = 0;
// score = 0;
// // double T = 10000, u = 0.9995;
// double t0 = 100.0; double c = 0.75;
// int trials = 1;
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// uniform_int_distribution u(0, M-1);
// geometric_distribution<int> g(0.4);
// double lambda = 0.01; vector<double> w(M); for (int i = 0; i < M; i++) w[i] = exp(-lambda * i);
// discrete_distribution<int> d(all(w));
// // while (T > 1) {
// while(best_score < K) {
// if (trials % 25000 == 0) cerr << "Trials: " << trials << " Best: " << best_score << "\n";
// if (trials % CHECK_EVERY == 0) save_checkpoint(CHECKPOINT_PATH, best, best_score, trials);
// double T = c / log(t0 + double(trials));
// vi nxt = cur;
// int idx = u(rng);
// // int val = g(rng) + 1; while (val >= M) val = g(rng) + 1;
// int val = d(rng); while (!(1 <= val && val < M)) val = d(rng);
// nxt[idx] = val;
// int ns = count_triples(nxt);
// if (accept(score, ns, T, rng)) {
// score = ns; cur = nxt;
// if (ns > best_score) {
// best_score = ns; best = nxt;
// }
// }
// // T *= u;
// trials++;
// }
// cerr << "Array has: " << count_triples(best) << " triples.\n";
// return best;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |