Submission #1258162

#TimeUsernameProblemLanguageResultExecution timeMemory
1258162madamadam33개의 봉우리 (IOI25_triples)C++20
75.09 / 100
1258 ms40220 KiB
#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 best(M, 1); int score = 0, best_score = 0; for (int tl = 0; tl < 2; tl++) { vi cur(M, 1); score = 0; // double T = 10000, u = 0.9995; double t0 = 100, c = 1.0; 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.1; 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) { int lim = (150'000 / M) * 20; while(trials < lim && best_score < K) { if (best_score >= K) break; if (trials % 10000 == 0) cerr << "Trials: " << trials << " Best: " << best_score << "\n"; 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 = u(rng); while (!(1 <= val && val < M)) val = u(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 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...
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...