Text Generation
Transformers
Safetensors
English
nemotron_h
nvidia
nemotron-cascade-2
reasoning
general-purpose
SFT
RL
conversational
custom_code
Eval Results
Instructions to use nvidia/Nemotron-Cascade-2-30B-A3B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use nvidia/Nemotron-Cascade-2-30B-A3B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="nvidia/Nemotron-Cascade-2-30B-A3B", trust_remote_code=True) messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("nvidia/Nemotron-Cascade-2-30B-A3B", trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained("nvidia/Nemotron-Cascade-2-30B-A3B", trust_remote_code=True, device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use nvidia/Nemotron-Cascade-2-30B-A3B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "nvidia/Nemotron-Cascade-2-30B-A3B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nvidia/Nemotron-Cascade-2-30B-A3B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/nvidia/Nemotron-Cascade-2-30B-A3B
- SGLang
How to use nvidia/Nemotron-Cascade-2-30B-A3B with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "nvidia/Nemotron-Cascade-2-30B-A3B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nvidia/Nemotron-Cascade-2-30B-A3B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "nvidia/Nemotron-Cascade-2-30B-A3B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "nvidia/Nemotron-Cascade-2-30B-A3B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use nvidia/Nemotron-Cascade-2-30B-A3B with Docker Model Runner:
docker model run hf.co/nvidia/Nemotron-Cascade-2-30B-A3B
Delete ioi2025
Browse files- ioi2025/festival.cpp +0 -140
- ioi2025/migrations-subtask1.cpp +0 -83
- ioi2025/migrations-subtask2.cpp +0 -190
- ioi2025/obstacles.cpp +0 -222
- ioi2025/souvenirs-subtask1_3.cpp +0 -46
- ioi2025/souvenirs-subtask4.cpp +0 -22
- ioi2025/triples-part1.cpp +0 -126
- ioi2025/triples-part2-subtask1.cpp +0 -141
- ioi2025/triples-part2-subtask2.cpp +0 -358
- ioi2025/triples-part2-subtask3.cpp +0 -196
- ioi2025/triples-part2-subtask4.cpp +0 -122
- ioi2025/triples-part2-subtask5.cpp +0 -141
- ioi2025/triples-part2-subtask6.cpp +0 -131
- ioi2025/worldmap.cpp +0 -202
ioi2025/festival.cpp
DELETED
|
@@ -1,140 +0,0 @@
|
|
| 1 |
-
#include <bits/stdc++.h>
|
| 2 |
-
using namespace std;
|
| 3 |
-
|
| 4 |
-
struct Booster {
|
| 5 |
-
long long price; // P[i]
|
| 6 |
-
int typ; // T[i] (2..4)
|
| 7 |
-
int idx; // original coupon index
|
| 8 |
-
double a; // P[i] * T[i] / (T[i]-1) for sorting
|
| 9 |
-
};
|
| 10 |
-
|
| 11 |
-
using ll = long long;
|
| 12 |
-
const ll INF64 = numeric_limits<long long>::max();
|
| 13 |
-
|
| 14 |
-
/*---------------------------------------------------------------*/
|
| 15 |
-
/* Main function required by the statement */
|
| 16 |
-
vector<int> max_coupons(int A,
|
| 17 |
-
vector<int> P,
|
| 18 |
-
vector<int> T)
|
| 19 |
-
{
|
| 20 |
-
const int N = (int)P.size();
|
| 21 |
-
|
| 22 |
-
/* ----------- 1. split into boosters and cheap coupons ----------- */
|
| 23 |
-
vector<Booster> boosters;
|
| 24 |
-
boosters.reserve(N);
|
| 25 |
-
vector<pair<ll,int>> cheap; // (price , idx)
|
| 26 |
-
cheap.reserve(N);
|
| 27 |
-
|
| 28 |
-
for (int i = 0; i < N; ++i) {
|
| 29 |
-
if (T[i] == 1) {
|
| 30 |
-
cheap.emplace_back(P[i], i);
|
| 31 |
-
} else {
|
| 32 |
-
Booster b;
|
| 33 |
-
b.price = P[i];
|
| 34 |
-
b.typ = T[i];
|
| 35 |
-
b.idx = i;
|
| 36 |
-
b.a = (double)P[i] * (double)T[i] / (double)(T[i] - 1);
|
| 37 |
-
boosters.push_back(b);
|
| 38 |
-
}
|
| 39 |
-
}
|
| 40 |
-
|
| 41 |
-
/* -------------------- 2. sort the two groups ------------------- */
|
| 42 |
-
sort(boosters.begin(), boosters.end(),
|
| 43 |
-
[](const Booster& x, const Booster& y){ return x.a < y.a; });
|
| 44 |
-
|
| 45 |
-
sort(cheap.begin(), cheap.end(),
|
| 46 |
-
[](const pair<ll,int>& x, const pair<ll,int>& y){ return x.first < y.first; });
|
| 47 |
-
|
| 48 |
-
int C = (int)cheap.size();
|
| 49 |
-
vector<ll> cheapPref(C + 1, 0); // cheapPref[0] = 0
|
| 50 |
-
vector<int> cheapIdx(C);
|
| 51 |
-
for (int i = 0; i < C; ++i) {
|
| 52 |
-
cheapPref[i+1] = cheapPref[i] + cheap[i].first;
|
| 53 |
-
cheapIdx[i] = cheap[i].second;
|
| 54 |
-
}
|
| 55 |
-
|
| 56 |
-
/* --------------------- 3. DP over boosters --------------------- */
|
| 57 |
-
// DP vectors – state id is its position in the vectors
|
| 58 |
-
vector<ll> tokens; // tokens left after the state
|
| 59 |
-
vector<int> cnts; // number of boosters taken in the state
|
| 60 |
-
vector<int> prev; // previous state id
|
| 61 |
-
vector<int> idxs; // coupon index of the last taken booster
|
| 62 |
-
|
| 63 |
-
tokens.push_back((ll)A); // state 0 – start
|
| 64 |
-
cnts .push_back(0);
|
| 65 |
-
prev .push_back(-1);
|
| 66 |
-
idxs .push_back(-1);
|
| 67 |
-
|
| 68 |
-
vector<int> frontier; // ids of non‑dominated states
|
| 69 |
-
frontier.push_back(0);
|
| 70 |
-
|
| 71 |
-
for (const Booster& b : boosters) {
|
| 72 |
-
vector<int> added; // newly created states (ids)
|
| 73 |
-
added.reserve(frontier.size());
|
| 74 |
-
|
| 75 |
-
for (int sid : frontier) {
|
| 76 |
-
if (tokens[sid] >= b.price) {
|
| 77 |
-
// (tokens[sid] - price) * typ – do it in 128‑bit to avoid overflow
|
| 78 |
-
__int128 tmp = (__int128)(tokens[sid] - b.price) * (ll)b.typ;
|
| 79 |
-
ll newTok = (tmp > INF64) ? INF64 : (ll)tmp;
|
| 80 |
-
|
| 81 |
-
tokens.push_back(newTok);
|
| 82 |
-
cnts .push_back(cnts[sid] + 1);
|
| 83 |
-
prev .push_back(sid);
|
| 84 |
-
idxs .push_back(b.idx);
|
| 85 |
-
added.push_back((int)tokens.size() - 1);
|
| 86 |
-
}
|
| 87 |
-
}
|
| 88 |
-
|
| 89 |
-
// ---- merge old and new states, keep only non‑dominated ----
|
| 90 |
-
vector<int> cand = frontier;
|
| 91 |
-
cand.insert(cand.end(), added.begin(), added.end());
|
| 92 |
-
|
| 93 |
-
sort(cand.begin(), cand.end(),
|
| 94 |
-
[&](int a, int b) {
|
| 95 |
-
if (tokens[a] != tokens[b]) return tokens[a] > tokens[b];
|
| 96 |
-
return cnts[a] > cnts[b];
|
| 97 |
-
});
|
| 98 |
-
|
| 99 |
-
vector<int> newFrontier;
|
| 100 |
-
int bestCnt = -1;
|
| 101 |
-
for (int sid : cand) {
|
| 102 |
-
if (cnts[sid] > bestCnt) {
|
| 103 |
-
newFrontier.push_back(sid);
|
| 104 |
-
bestCnt = cnts[sid];
|
| 105 |
-
}
|
| 106 |
-
}
|
| 107 |
-
frontier.swap(newFrontier);
|
| 108 |
-
}
|
| 109 |
-
|
| 110 |
-
/* -------------------- 4. Choose the best final state -------------------- */
|
| 111 |
-
long long bestTotal = -1;
|
| 112 |
-
int bestState = -1;
|
| 113 |
-
int bestCheap = 0; // how many cheap coupons we can buy
|
| 114 |
-
|
| 115 |
-
for (int sid : frontier) {
|
| 116 |
-
ll curTok = tokens[sid];
|
| 117 |
-
// number of cheap coupons affordable with curTok tokens
|
| 118 |
-
int cheapCnt = (int)(upper_bound(cheapPref.begin(), cheapPref.end(), curTok)
|
| 119 |
-
- cheapPref.begin()) - 1;
|
| 120 |
-
long long total = (long long)cnts[sid] + cheapCnt;
|
| 121 |
-
if (total > bestTotal) {
|
| 122 |
-
bestTotal = total;
|
| 123 |
-
bestState = sid;
|
| 124 |
-
bestCheap = cheapCnt;
|
| 125 |
-
}
|
| 126 |
-
}
|
| 127 |
-
|
| 128 |
-
/* -------------------- 5. Reconstruct the answer -------------------- */
|
| 129 |
-
vector<int> answer;
|
| 130 |
-
// boosters (taken in reverse order)
|
| 131 |
-
for (int sid = bestState; sid != 0; sid = prev[sid])
|
| 132 |
-
answer.push_back(idxs[sid]);
|
| 133 |
-
reverse(answer.begin(), answer.end());
|
| 134 |
-
|
| 135 |
-
// cheap coupons – they are already sorted by price
|
| 136 |
-
for (int i = 0; i < bestCheap; ++i)
|
| 137 |
-
answer.push_back(cheapIdx[i]);
|
| 138 |
-
|
| 139 |
-
return answer;
|
| 140 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/migrations-subtask1.cpp
DELETED
|
@@ -1,83 +0,0 @@
|
|
| 1 |
-
// ------------------------------------------------------------
|
| 2 |
-
// Dinosaur migration – research team (send_message) and Museum
|
| 3 |
-
// ------------------------------------------------------------
|
| 4 |
-
|
| 5 |
-
#include <vector>
|
| 6 |
-
#include <utility> // std::pair
|
| 7 |
-
#include <algorithm> // std::max
|
| 8 |
-
|
| 9 |
-
// -----------------------------------------------------------------
|
| 10 |
-
// Constants and global data that survive across calls of send_message
|
| 11 |
-
// -----------------------------------------------------------------
|
| 12 |
-
static const int _BLOCK = 100; // block size for the encoding
|
| 13 |
-
|
| 14 |
-
// current test case size (0 means “no test case started yet”)
|
| 15 |
-
static int _curr_N = -1;
|
| 16 |
-
|
| 17 |
-
// depth[v] for the vertices that have already been visited
|
| 18 |
-
static std::vector<int> _depth;
|
| 19 |
-
|
| 20 |
-
// deepest distance seen so far and the *largest* vertex that attains it
|
| 21 |
-
static int _max_depth = -1;
|
| 22 |
-
static int _max_node = -1;
|
| 23 |
-
|
| 24 |
-
int send_message(int N, int i, int Pi)
|
| 25 |
-
{
|
| 26 |
-
// (re)initialise the data structures when we get a new test case
|
| 27 |
-
if (N != _curr_N) {
|
| 28 |
-
_curr_N = N;
|
| 29 |
-
_depth.assign(N, 0); // depth[0] stays 0, others are filled later
|
| 30 |
-
_max_depth = -1;
|
| 31 |
-
_max_node = -1;
|
| 32 |
-
}
|
| 33 |
-
|
| 34 |
-
// depth of the current vertex
|
| 35 |
-
int d = _depth[Pi] + 1;
|
| 36 |
-
_depth[i] = d;
|
| 37 |
-
|
| 38 |
-
// keep the deepest vertex seen so far (largest index on ties)
|
| 39 |
-
if (d > _max_depth || (d == _max_depth && i > _max_node)) {
|
| 40 |
-
_max_depth = d;
|
| 41 |
-
_max_node = i;
|
| 42 |
-
}
|
| 43 |
-
|
| 44 |
-
// decide what (if anything) to send from site i
|
| 45 |
-
if (i == N - 2) { // second‑last site – send block part
|
| 46 |
-
int block = _max_node / _BLOCK; // integer division, always >= 0
|
| 47 |
-
return block + 1; // 1 … 100
|
| 48 |
-
}
|
| 49 |
-
else if (i == N - 1) { // last site – send remainder part
|
| 50 |
-
int rem = _max_node % _BLOCK; // remainder in [0, 99]
|
| 51 |
-
return rem + 1; // 1 … 100
|
| 52 |
-
}
|
| 53 |
-
else {
|
| 54 |
-
return 0; // no message
|
| 55 |
-
}
|
| 56 |
-
}
|
| 57 |
-
|
| 58 |
-
std::pair<int,int> longest_path(std::vector<int> S)
|
| 59 |
-
{
|
| 60 |
-
const int N = static_cast<int>(S.size());
|
| 61 |
-
|
| 62 |
-
if (N == 1) {
|
| 63 |
-
return {0, 0};
|
| 64 |
-
}
|
| 65 |
-
|
| 66 |
-
// The two last entries are the encoded answer.
|
| 67 |
-
int block_val = S[N - 2];
|
| 68 |
-
int rem_val = S[N - 1];
|
| 69 |
-
|
| 70 |
-
// Convert back to the original block index (0‑based) and remainder.
|
| 71 |
-
int block = (block_val > 0) ? (block_val - 1) : 0; // 0 … 99
|
| 72 |
-
int rem = (rem_val > 0) ? (rem_val - 1) : 0; // 0 … 99
|
| 73 |
-
|
| 74 |
-
// Re‑assemble the index of the farthest vertex.
|
| 75 |
-
int idx = block * _BLOCK + rem;
|
| 76 |
-
|
| 77 |
-
if (idx < 0) idx = 0;
|
| 78 |
-
else if (idx >= N) idx = N - 1;
|
| 79 |
-
|
| 80 |
-
// Site 0 is always an endpoint of a diameter (as required by the
|
| 81 |
-
// original research problem). The second endpoint is `idx`.
|
| 82 |
-
return {0, idx};
|
| 83 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/migrations-subtask2.cpp
DELETED
|
@@ -1,190 +0,0 @@
|
|
| 1 |
-
#include <bits/stdc++.h>
|
| 2 |
-
using namespace std;
|
| 3 |
-
|
| 4 |
-
/* -----------------------------------------------------------------
|
| 5 |
-
Global state that is shared between successive calls of
|
| 6 |
-
send_message for the *same* test case.
|
| 7 |
-
It is re‑initialised each time the first node (i == 1) of a new
|
| 8 |
-
test case is processed.
|
| 9 |
-
----------------------------------------------------------------- */
|
| 10 |
-
namespace {
|
| 11 |
-
// total number of vertices of the current test case
|
| 12 |
-
static int total_nodes = 0;
|
| 13 |
-
// binary‑lifting depth
|
| 14 |
-
static int LOG = 0;
|
| 15 |
-
static vector<int> depth; // depth[v]
|
| 16 |
-
static vector<vector<int>> up; // up[k][v] = 2^k‑th ancestor
|
| 17 |
-
|
| 18 |
-
// current diameter (a,b) and its length
|
| 19 |
-
static int a = 0, b = 0, diam = 0;
|
| 20 |
-
|
| 21 |
-
// auxiliary values that are saved at specific steps
|
| 22 |
-
static int a2 = -1; // a after node N‑2
|
| 23 |
-
static int b2 = -1; // b after node N‑2
|
| 24 |
-
static int b_at_N3 = -1; // b after node N‑3
|
| 25 |
-
}
|
| 26 |
-
|
| 27 |
-
/* -----------------------------------------------------------------
|
| 28 |
-
Helper functions working on the global structures
|
| 29 |
-
----------------------------------------------------------------- */
|
| 30 |
-
static void reinit(int N)
|
| 31 |
-
{
|
| 32 |
-
total_nodes = N;
|
| 33 |
-
LOG = 0;
|
| 34 |
-
while ((1 << LOG) <= N) ++LOG; // floor(log2(N)) + 1
|
| 35 |
-
++LOG; // a little safety margin
|
| 36 |
-
|
| 37 |
-
depth.assign(N, 0); // depth[0] = 0 already
|
| 38 |
-
up.assign(LOG, vector<int>(N, 0)); // all ancestors of the root = 0
|
| 39 |
-
|
| 40 |
-
a = b = diam = 0;
|
| 41 |
-
a2 = b2 = -1;
|
| 42 |
-
b_at_N3 = -1;
|
| 43 |
-
}
|
| 44 |
-
|
| 45 |
-
/* LCA by binary lifting */
|
| 46 |
-
static int lca(int u, int v)
|
| 47 |
-
{
|
| 48 |
-
if (depth[u] < depth[v]) swap(u, v);
|
| 49 |
-
int diff = depth[u] - depth[v];
|
| 50 |
-
for (int k = 0; diff; ++k) {
|
| 51 |
-
if (diff & 1) u = up[k][u];
|
| 52 |
-
diff >>= 1;
|
| 53 |
-
}
|
| 54 |
-
if (u == v) return u;
|
| 55 |
-
for (int k = LOG - 1; k >= 0; --k) {
|
| 56 |
-
if (up[k][u] != up[k][v]) {
|
| 57 |
-
u = up[k][u];
|
| 58 |
-
v = up[k][v];
|
| 59 |
-
}
|
| 60 |
-
}
|
| 61 |
-
return up[0][u];
|
| 62 |
-
}
|
| 63 |
-
|
| 64 |
-
/* Distance between two vertices */
|
| 65 |
-
static int dist(int u, int v)
|
| 66 |
-
{
|
| 67 |
-
int w = lca(u, v);
|
| 68 |
-
return depth[u] + depth[v] - 2 * depth[w];
|
| 69 |
-
}
|
| 70 |
-
|
| 71 |
-
/* -----------------------------------------------------------------
|
| 72 |
-
send_message – called while the tree is being built (sites 1 … N‑1)
|
| 73 |
-
Returns 0 (no message) or an integer that will be sent to the museum.
|
| 74 |
-
----------------------------------------------------------------- */
|
| 75 |
-
int send_message(int N, int i, int Pi) // C‑link for clarity
|
| 76 |
-
{
|
| 77 |
-
// first call of a new test case → initialise the global data
|
| 78 |
-
if (i == 1) {
|
| 79 |
-
reinit(N);
|
| 80 |
-
}
|
| 81 |
-
|
| 82 |
-
/* ---- insert the new leaf i (parent = Pi) ---- */
|
| 83 |
-
int d = depth[Pi] + 1;
|
| 84 |
-
depth[i] = d;
|
| 85 |
-
up[0][i] = Pi;
|
| 86 |
-
for (int k = 1; k < LOG; ++k) {
|
| 87 |
-
int anc = up[k - 1][i];
|
| 88 |
-
up[k][i] = up[k - 1][anc];
|
| 89 |
-
}
|
| 90 |
-
|
| 91 |
-
/* ---- maintain the current diameter (a,b) ---- */
|
| 92 |
-
int da = dist(i, a);
|
| 93 |
-
int db = dist(i, b);
|
| 94 |
-
if (da > diam) {
|
| 95 |
-
b = i;
|
| 96 |
-
diam = da;
|
| 97 |
-
} else if (db > diam) {
|
| 98 |
-
a = i;
|
| 99 |
-
diam = db;
|
| 100 |
-
}
|
| 101 |
-
|
| 102 |
-
/* ---- send the three tiny messages (only at i = N‑3, N‑2, N‑1) ---- */
|
| 103 |
-
if (total_nodes >= 4 && i == total_nodes - 3 && i >= 1) {
|
| 104 |
-
/* i == N‑3 : store b after node N‑3 (store +1 because 0 would be ambiguous) */
|
| 105 |
-
b_at_N3 = b;
|
| 106 |
-
return b + 1; // 1 ≤ value ≤ 20000
|
| 107 |
-
}
|
| 108 |
-
else if (i == total_nodes - 2 && i >= 1) {
|
| 109 |
-
/* i == N‑2 : store a and the whole diameter after this step */
|
| 110 |
-
a2 = a;
|
| 111 |
-
b2 = b;
|
| 112 |
-
return a + 1; // a+1 (still ≤ 20000)
|
| 113 |
-
}
|
| 114 |
-
else if (i == total_nodes - 1 && i >= 1) {
|
| 115 |
-
/* i == N‑1 : compute the flag (1 … 5) */
|
| 116 |
-
int a_final = a;
|
| 117 |
-
int b_final = b;
|
| 118 |
-
int a2_local = a2;
|
| 119 |
-
int b2_local = b2;
|
| 120 |
-
int b0 = b_at_N3; // b after node N‑3 (may be outdated)
|
| 121 |
-
|
| 122 |
-
int flag = 1; // default (fallback)
|
| 123 |
-
|
| 124 |
-
if (a_final == a2_local && b_final == b2_local) {
|
| 125 |
-
flag = (b2_local == total_nodes - 2) ? 2 : 1;
|
| 126 |
-
}
|
| 127 |
-
else if (a_final == a2_local && b_final == total_nodes - 1) {
|
| 128 |
-
flag = 3; // b replaced at the last insertion
|
| 129 |
-
}
|
| 130 |
-
else if (a_final == total_nodes - 1 && b_final == b2_local) {
|
| 131 |
-
flag = (b2_local == total_nodes - 2) ? 5 : 4;
|
| 132 |
-
}
|
| 133 |
-
else {
|
| 134 |
-
flag = 1; // should never happen
|
| 135 |
-
}
|
| 136 |
-
|
| 137 |
-
return flag; // already in [1,5]
|
| 138 |
-
}
|
| 139 |
-
|
| 140 |
-
return 0; // all other vertices: no message
|
| 141 |
-
}
|
| 142 |
-
|
| 143 |
-
/* -----------------------------------------------------------------
|
| 144 |
-
longest_path – decodes the three messages produced by send_message
|
| 145 |
-
and returns a pair of vertices that realise the tree diameter.
|
| 146 |
-
----------------------------------------------------------------- */
|
| 147 |
-
pair<int,int> longest_path(vector<int> S)
|
| 148 |
-
{
|
| 149 |
-
size_t N = S.size();
|
| 150 |
-
|
| 151 |
-
if (N <= 1) return {0, 0};
|
| 152 |
-
if (N == 2) return {0, 1};
|
| 153 |
-
if (N == 3) return {1, 2};
|
| 154 |
-
|
| 155 |
-
// N >= 4 : three stored values are at positions N‑3, N‑2, N‑1
|
| 156 |
-
int a_msg = S[N - 2]; // a after node N‑2 (+1)
|
| 157 |
-
int b_msg = S[N - 3]; // b after node N‑3 (+1)
|
| 158 |
-
int flag = S[N - 1]; // 1 … 5
|
| 159 |
-
|
| 160 |
-
int a = a_msg - 1; // a after node N‑2
|
| 161 |
-
int b0 = b_msg - 1; // b after node N‑3
|
| 162 |
-
|
| 163 |
-
int u, v;
|
| 164 |
-
switch (flag) {
|
| 165 |
-
case 1: // both old endpoints survive
|
| 166 |
-
u = a;
|
| 167 |
-
v = b0;
|
| 168 |
-
break;
|
| 169 |
-
case 2: // b changed at N‑2, a survived
|
| 170 |
-
u = a;
|
| 171 |
-
v = static_cast<int>(N) - 2;
|
| 172 |
-
break;
|
| 173 |
-
case 3: // b replaced at N‑1, a survived
|
| 174 |
-
u = a;
|
| 175 |
-
v = static_cast<int>(N) - 1;
|
| 176 |
-
break;
|
| 177 |
-
case 4: // a replaced at N‑1, b survived (b unchanged at N‑2)
|
| 178 |
-
u = b0;
|
| 179 |
-
v = static_cast<int>(N) - 1;
|
| 180 |
-
break;
|
| 181 |
-
case 5: // a replaced at N‑1, b changed at N‑2
|
| 182 |
-
u = static_cast<int>(N) - 2;
|
| 183 |
-
v = static_cast<int>(N) - 1;
|
| 184 |
-
break;
|
| 185 |
-
default: // safety fallback – should never be hit
|
| 186 |
-
u = a;
|
| 187 |
-
v = b0;
|
| 188 |
-
}
|
| 189 |
-
return {u, v};
|
| 190 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/obstacles.cpp
DELETED
|
@@ -1,222 +0,0 @@
|
|
| 1 |
-
#include <bits/stdc++.h>
|
| 2 |
-
using namespace std;
|
| 3 |
-
|
| 4 |
-
/* ------------------------------------------------------------------ */
|
| 5 |
-
/* Disjoint Set Union (Union–Find) */
|
| 6 |
-
/* ------------------------------------------------------------------ */
|
| 7 |
-
struct DSU {
|
| 8 |
-
vector<int> parent, sz;
|
| 9 |
-
DSU(int n = 0) { init(n); }
|
| 10 |
-
|
| 11 |
-
void init(int n) {
|
| 12 |
-
parent.resize(n);
|
| 13 |
-
sz.assign(n, 1);
|
| 14 |
-
iota(parent.begin(), parent.end(), 0);
|
| 15 |
-
}
|
| 16 |
-
|
| 17 |
-
int find(int x) {
|
| 18 |
-
while (parent[x] != x) {
|
| 19 |
-
parent[x] = parent[parent[x]];
|
| 20 |
-
x = parent[x];
|
| 21 |
-
}
|
| 22 |
-
return x;
|
| 23 |
-
}
|
| 24 |
-
|
| 25 |
-
void union_sets(int a, int b) {
|
| 26 |
-
a = find(a);
|
| 27 |
-
b = find(b);
|
| 28 |
-
if (a == b) return;
|
| 29 |
-
if (sz[a] < sz[b]) swap(a, b);
|
| 30 |
-
parent[b] = a;
|
| 31 |
-
sz[a] += sz[b];
|
| 32 |
-
}
|
| 33 |
-
};
|
| 34 |
-
|
| 35 |
-
/* ------------------------------------------------------------------ */
|
| 36 |
-
/* Segment tree for range maximum (static) */
|
| 37 |
-
/* ------------------------------------------------------------------ */
|
| 38 |
-
struct MaxSegTree {
|
| 39 |
-
int n; // original size
|
| 40 |
-
int size; // power of two >= n
|
| 41 |
-
vector<int> tree; // 2*size elements
|
| 42 |
-
|
| 43 |
-
MaxSegTree() : n(0), size(0) {}
|
| 44 |
-
|
| 45 |
-
explicit MaxSegTree(const vector<int>& data) {
|
| 46 |
-
build(data);
|
| 47 |
-
}
|
| 48 |
-
|
| 49 |
-
void build(const vector<int>& data) {
|
| 50 |
-
n = static_cast<int>(data.size());
|
| 51 |
-
size = 1;
|
| 52 |
-
while (size < n) size <<= 1;
|
| 53 |
-
tree.assign(2 * size, 0);
|
| 54 |
-
for (int i = 0; i < n; ++i) tree[size + i] = data[i];
|
| 55 |
-
for (int i = size - 1; i > 0; --i)
|
| 56 |
-
tree[i] = max(tree[i << 1], tree[i << 1 | 1]);
|
| 57 |
-
}
|
| 58 |
-
|
| 59 |
-
// inclusive query [l, r]; returns -1 for empty interval
|
| 60 |
-
int query(int l, int r) const {
|
| 61 |
-
if (l > r) return -1;
|
| 62 |
-
l += size; r += size;
|
| 63 |
-
int res = -1;
|
| 64 |
-
while (l <= r) {
|
| 65 |
-
if (l & 1) res = max(res, tree[l++]);
|
| 66 |
-
if (!(r & 1)) res = max(res, tree[r--]);
|
| 67 |
-
l >>= 1; r >>= 1;
|
| 68 |
-
}
|
| 69 |
-
return res;
|
| 70 |
-
}
|
| 71 |
-
};
|
| 72 |
-
|
| 73 |
-
/* ------------------------------------------------------------------ */
|
| 74 |
-
/* Segment tree that stores min / max *active* column indices */
|
| 75 |
-
/* ------------------------------------------------------------------ */
|
| 76 |
-
struct ActiveSegTree {
|
| 77 |
-
int n; // number of columns
|
| 78 |
-
int size; // power of two >= n
|
| 79 |
-
vector<int> max_tree; // maximum active index inside the node
|
| 80 |
-
vector<int> min_tree; // minimum active index inside the node
|
| 81 |
-
|
| 82 |
-
explicit ActiveSegTree(int n_) : n(n_) {
|
| 83 |
-
size = 1;
|
| 84 |
-
while (size < n) size <<= 1;
|
| 85 |
-
max_tree.assign(2 * size, -1);
|
| 86 |
-
min_tree.assign(2 * size, n);
|
| 87 |
-
}
|
| 88 |
-
|
| 89 |
-
// mark column idx as active
|
| 90 |
-
void activate(int idx) {
|
| 91 |
-
int i = idx + size;
|
| 92 |
-
max_tree[i] = idx;
|
| 93 |
-
min_tree[i] = idx;
|
| 94 |
-
for (i >>= 1; i; i >>= 1) {
|
| 95 |
-
int left = i << 1;
|
| 96 |
-
int right = left | 1;
|
| 97 |
-
max_tree[i] = max(max_tree[left], max_tree[right]);
|
| 98 |
-
min_tree[i] = min(min_tree[left], min_tree[right]);
|
| 99 |
-
}
|
| 100 |
-
}
|
| 101 |
-
|
| 102 |
-
// maximum active index in [l, r]; -1 if none
|
| 103 |
-
int query_max(int l, int r) const {
|
| 104 |
-
if (l > r) return -1;
|
| 105 |
-
l += size; r += size;
|
| 106 |
-
int res = -1;
|
| 107 |
-
while (l <= r) {
|
| 108 |
-
if (l & 1) res = max(res, max_tree[l++]);
|
| 109 |
-
if (!(r & 1)) res = max(res, max_tree[r--]);
|
| 110 |
-
l >>= 1; r >>= 1;
|
| 111 |
-
}
|
| 112 |
-
return res;
|
| 113 |
-
}
|
| 114 |
-
|
| 115 |
-
// minimum active index in [l, r]; n if none
|
| 116 |
-
int query_min(int l, int r) const {
|
| 117 |
-
if (l > r) return n;
|
| 118 |
-
l += size; r += size;
|
| 119 |
-
int res = n;
|
| 120 |
-
while (l <= r) {
|
| 121 |
-
if (l & 1) res = min(res, min_tree[l++]);
|
| 122 |
-
if (!(r & 1)) res = min(res, min_tree[r--]);
|
| 123 |
-
l >>= 1; r >>= 1;
|
| 124 |
-
}
|
| 125 |
-
return res;
|
| 126 |
-
}
|
| 127 |
-
};
|
| 128 |
-
|
| 129 |
-
int N = 0, M = 0;
|
| 130 |
-
vector<int> pref_max; // prefix maximum of T, length N
|
| 131 |
-
vector<int> comp; // component id for each column
|
| 132 |
-
DSU* dsu = nullptr; // created inside initialize
|
| 133 |
-
|
| 134 |
-
/* ------------------------------------------------------------------ */
|
| 135 |
-
/* Interface required by the statement */
|
| 136 |
-
/* ------------------------------------------------------------------ */
|
| 137 |
-
void initialize(vector<int> T, vector<int> H)
|
| 138 |
-
{
|
| 139 |
-
N = static_cast<int>(T.size());
|
| 140 |
-
M = static_cast<int>(H.size());
|
| 141 |
-
|
| 142 |
-
/* 1. prefix maximum of temperatures */
|
| 143 |
-
pref_max.assign(N, 0);
|
| 144 |
-
pref_max[0] = T[0];
|
| 145 |
-
for (int i = 1; i < N; ++i)
|
| 146 |
-
pref_max[i] = max(pref_max[i-1], T[i]);
|
| 147 |
-
|
| 148 |
-
/* 2. first blocked row for every column */
|
| 149 |
-
vector<int> col_by_h(M);
|
| 150 |
-
iota(col_by_h.begin(), col_by_h.end(), 0);
|
| 151 |
-
sort(col_by_h.begin(), col_by_h.end(),
|
| 152 |
-
[&](int a, int b){ return H[a] > H[b]; });
|
| 153 |
-
|
| 154 |
-
vector<int> first_block(M, N);
|
| 155 |
-
int ptr = 0;
|
| 156 |
-
for (int i = 0; i < N; ++i) {
|
| 157 |
-
int ti = T[i];
|
| 158 |
-
while (ptr < M && H[col_by_h[ptr]] >= ti) {
|
| 159 |
-
int col = col_by_h[ptr];
|
| 160 |
-
first_block[col] = i;
|
| 161 |
-
++ptr;
|
| 162 |
-
}
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
vector<int> Lcol(M);
|
| 166 |
-
for (int j = 0; j < M; ++j) {
|
| 167 |
-
if (first_block[j] == N) Lcol[j] = N - 1;
|
| 168 |
-
else Lcol[j] = first_block[j] - 1;
|
| 169 |
-
}
|
| 170 |
-
|
| 171 |
-
/* 3. V[j] = max temperature in rows 0 … Lcol[j] */
|
| 172 |
-
vector<int> V(M);
|
| 173 |
-
for (int j = 0; j < M; ++j) {
|
| 174 |
-
if (Lcol[j] >= 0) V[j] = pref_max[Lcol[j]];
|
| 175 |
-
else V[j] = -1; // column can never be reached
|
| 176 |
-
}
|
| 177 |
-
|
| 178 |
-
/* 4. segment tree for range maximum of humidity (static) */
|
| 179 |
-
MaxSegTree seg_H(H);
|
| 180 |
-
|
| 181 |
-
/* 5. DSU over columns */
|
| 182 |
-
dsu = new DSU(M);
|
| 183 |
-
|
| 184 |
-
/* 6. process columns in decreasing V */
|
| 185 |
-
vector<int> order(M);
|
| 186 |
-
iota(order.begin(), order.end(), 0);
|
| 187 |
-
sort(order.begin(), order.end(),
|
| 188 |
-
[&](int a, int b){ return V[a] > V[b]; });
|
| 189 |
-
|
| 190 |
-
ActiveSegTree active_seg(M); // no column active at the beginning
|
| 191 |
-
|
| 192 |
-
for (int col : order) {
|
| 193 |
-
int vcol = V[col];
|
| 194 |
-
active_seg.activate(col); // make the column active
|
| 195 |
-
|
| 196 |
-
// ---- left neighbour ----
|
| 197 |
-
int left = -1;
|
| 198 |
-
if (col > 0) left = active_seg.query_max(0, col - 1);
|
| 199 |
-
if (left != -1) {
|
| 200 |
-
int max_h = seg_H.query(left, col);
|
| 201 |
-
if (max_h < vcol) dsu->union_sets(col, left);
|
| 202 |
-
}
|
| 203 |
-
|
| 204 |
-
// ---- right neighbour ----
|
| 205 |
-
int right = M;
|
| 206 |
-
if (col + 1 < M) right = active_seg.query_min(col + 1, M - 1);
|
| 207 |
-
if (right != M) {
|
| 208 |
-
int max_h = seg_H.query(col, right);
|
| 209 |
-
if (max_h < vcol) dsu->union_sets(col, right);
|
| 210 |
-
}
|
| 211 |
-
}
|
| 212 |
-
|
| 213 |
-
/* 7. store the component id for every column */
|
| 214 |
-
comp.resize(M);
|
| 215 |
-
for (int i = 0; i < M; ++i) comp[i] = dsu->find(i);
|
| 216 |
-
}
|
| 217 |
-
|
| 218 |
-
bool can_reach(int L, int R, int S, int D)
|
| 219 |
-
{
|
| 220 |
-
(void)L; (void)R; // unused, required by the signature
|
| 221 |
-
return comp[S] == comp[D];
|
| 222 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/souvenirs-subtask1_3.cpp
DELETED
|
@@ -1,46 +0,0 @@
|
|
| 1 |
-
#include <vector>
|
| 2 |
-
#include <utility>
|
| 3 |
-
|
| 4 |
-
using namespace std;
|
| 5 |
-
|
| 6 |
-
// Provided by the judge. It returns the list of types bought and the
|
| 7 |
-
// number of coins that remain after giving M coins.
|
| 8 |
-
pair<vector<int>, long long> transaction(long long M);
|
| 9 |
-
|
| 10 |
-
void buy_souvenirs(int N, long long P0)
|
| 11 |
-
{
|
| 12 |
-
vector<long long> price(N, 0);
|
| 13 |
-
vector<int> bought(N, 0);
|
| 14 |
-
|
| 15 |
-
price[0] = P0; // price of type 0 is known
|
| 16 |
-
|
| 17 |
-
// -------- Phase 1 : discover all prices ----------
|
| 18 |
-
for (int i = 1; i < N; ++i) {
|
| 19 |
-
long long M = price[i - 1] - 1; // guaranteed < price[i-1] and ≥ price[i]
|
| 20 |
-
auto [L, R] = transaction(M); // L – bought types, R – remaining coins
|
| 21 |
-
|
| 22 |
-
for (int t : L) ++bought[t];
|
| 23 |
-
|
| 24 |
-
long long spent = M - R; // total money spent in this transaction
|
| 25 |
-
|
| 26 |
-
if (L.size() == 1) {
|
| 27 |
-
price[i] = spent; // only type i was bought
|
| 28 |
-
} else {
|
| 29 |
-
price[i] = spent - 1; // cheapest type (price 1) was also bought
|
| 30 |
-
int extra = -1;
|
| 31 |
-
for (int t : L) if (t != i) { extra = t; break; }
|
| 32 |
-
if (extra != -1 && price[extra] == 0) {
|
| 33 |
-
price[extra] = 1; // cheapest type has price 1
|
| 34 |
-
}
|
| 35 |
-
}
|
| 36 |
-
}
|
| 37 |
-
|
| 38 |
-
// -------- Phase 2 : buy the remaining copies ----------
|
| 39 |
-
for (int i = 1; i < N; ++i) {
|
| 40 |
-
while (bought[i] < i) {
|
| 41 |
-
long long M = price[i]; // give exactly the price of type i
|
| 42 |
-
auto [L, R] = transaction(M);
|
| 43 |
-
for (int t : L) ++bought[t];
|
| 44 |
-
}
|
| 45 |
-
}
|
| 46 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/souvenirs-subtask4.cpp
DELETED
|
@@ -1,22 +0,0 @@
|
|
| 1 |
-
#include <vector>
|
| 2 |
-
#include <utility>
|
| 3 |
-
|
| 4 |
-
std::pair<std::vector<int>, long long> transaction(long long M); // provided by the judge
|
| 5 |
-
|
| 6 |
-
void buy_souvenirs(int N, long long P0)
|
| 7 |
-
{
|
| 8 |
-
long long M1 = P0 - 1;
|
| 9 |
-
auto [L1, R1] = transaction(M1);
|
| 10 |
-
|
| 11 |
-
if (L1.size() == 2) {
|
| 12 |
-
long long S = M1 - R1;
|
| 13 |
-
long long M2 = S / 2;
|
| 14 |
-
transaction(M2);
|
| 15 |
-
return;
|
| 16 |
-
}
|
| 17 |
-
|
| 18 |
-
long long P1 = M1 - R1;
|
| 19 |
-
long long M = P1 - 1;
|
| 20 |
-
transaction(M);
|
| 21 |
-
transaction(M);
|
| 22 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/triples-part1.cpp
DELETED
|
@@ -1,126 +0,0 @@
|
|
| 1 |
-
#include <bits/stdc++.h>
|
| 2 |
-
using namespace std;
|
| 3 |
-
|
| 4 |
-
long long count_triples(vector<int> H)
|
| 5 |
-
{
|
| 6 |
-
const int N = static_cast<int>(H.size());
|
| 7 |
-
|
| 8 |
-
long long cnt1 = 0, cnt2 = 0, cnt3 = 0, cnt4 = 0,
|
| 9 |
-
cnt5 = 0, cnt6 = 0, equal_cnt = 0;
|
| 10 |
-
|
| 11 |
-
/* ---------- assignment 1 ---------- */
|
| 12 |
-
for (int i = 0; i < N; ++i) {
|
| 13 |
-
int j = i + H[i];
|
| 14 |
-
if (j >= N) continue;
|
| 15 |
-
int b = H[j];
|
| 16 |
-
int k = j + b;
|
| 17 |
-
if (k >= N) continue;
|
| 18 |
-
if (H[k] == H[i] + b) ++cnt1;
|
| 19 |
-
}
|
| 20 |
-
|
| 21 |
-
/* ---------- assignment 2 ---------- */
|
| 22 |
-
for (int i = 0; i < N; ++i) {
|
| 23 |
-
int j = i + H[i];
|
| 24 |
-
if (j >= N) continue;
|
| 25 |
-
int b = H[j] - H[i];
|
| 26 |
-
if (b <= 0) continue;
|
| 27 |
-
int k = j + b;
|
| 28 |
-
if (k >= N) continue;
|
| 29 |
-
if (H[k] == b) ++cnt2;
|
| 30 |
-
}
|
| 31 |
-
|
| 32 |
-
/* ---------- assignment 3 ---------- */
|
| 33 |
-
for (int j = 0; j < N; ++j) {
|
| 34 |
-
int i = j - H[j];
|
| 35 |
-
if (i < 0) continue;
|
| 36 |
-
int b = H[i];
|
| 37 |
-
int k = j + b;
|
| 38 |
-
if (k >= N) continue;
|
| 39 |
-
if (H[k] == H[j] + b) ++cnt3;
|
| 40 |
-
}
|
| 41 |
-
|
| 42 |
-
/* ---------- assignment 5 ---------- */
|
| 43 |
-
for (int j = 0; j < N; ++j) {
|
| 44 |
-
int i = j - H[j];
|
| 45 |
-
if (i < 0) continue;
|
| 46 |
-
int b = H[i] - H[j];
|
| 47 |
-
if (b <= 0) continue;
|
| 48 |
-
int k = j + b;
|
| 49 |
-
if (k >= N) continue;
|
| 50 |
-
if (H[k] == b) ++cnt5;
|
| 51 |
-
}
|
| 52 |
-
|
| 53 |
-
/* ---------- assignment 6 ---------- */
|
| 54 |
-
for (int j = 0; j < N; ++j) {
|
| 55 |
-
int k = j + H[j];
|
| 56 |
-
if (k >= N) continue;
|
| 57 |
-
int a = H[k];
|
| 58 |
-
int i = j - a;
|
| 59 |
-
if (i < 0) continue;
|
| 60 |
-
if (H[i] == a + H[j]) ++cnt6;
|
| 61 |
-
}
|
| 62 |
-
|
| 63 |
-
/* ---------- assignment 4 (group i+H[i] = k-H[k]) ---------- */
|
| 64 |
-
// groups[T] = list of k such that k - H[k] == T (T = “key”)
|
| 65 |
-
unordered_map<int, vector<int>> groups;
|
| 66 |
-
groups.reserve(N * 2);
|
| 67 |
-
for (int k = 0; k < N; ++k) {
|
| 68 |
-
int T = k - H[k];
|
| 69 |
-
groups[T].push_back(k); // k grows, so each vector stays sorted
|
| 70 |
-
}
|
| 71 |
-
|
| 72 |
-
for (int i = 0; i < N; ++i) {
|
| 73 |
-
int T = i + H[i];
|
| 74 |
-
auto it = groups.find(T);
|
| 75 |
-
if (it == groups.end()) continue; // no k with the needed key
|
| 76 |
-
|
| 77 |
-
const vector<int>& ks = it->second;
|
| 78 |
-
// first k that is > i
|
| 79 |
-
auto posIter = upper_bound(ks.begin(), ks.end(), i);
|
| 80 |
-
int H_i = H[i];
|
| 81 |
-
|
| 82 |
-
for (auto kIt = posIter; kIt != ks.end(); ++kIt) {
|
| 83 |
-
int k = *kIt;
|
| 84 |
-
int j = k - H_i;
|
| 85 |
-
if (j >= N) break; // larger k → larger j, so we can stop
|
| 86 |
-
// i < j < k holds automatically for the chosen ks
|
| 87 |
-
if (H[j] == k - i) ++cnt4;
|
| 88 |
-
}
|
| 89 |
-
}
|
| 90 |
-
|
| 91 |
-
long long total = cnt1 + cnt2 + cnt3 + cnt4 + cnt5 + cnt6;
|
| 92 |
-
|
| 93 |
-
/* ---------- triples with equal distances (a = b) ----------
|
| 94 |
-
These triples were counted twice (once in the main total and
|
| 95 |
-
once in the equal‑distance special case), therefore we subtract
|
| 96 |
-
them once at the end. */
|
| 97 |
-
for (int i = 0; i < N; ++i) {
|
| 98 |
-
int a = H[i];
|
| 99 |
-
|
| 100 |
-
// case 1 : distance = a (i → j → k, with j = i+a, k = i+2a)
|
| 101 |
-
int j = i + a;
|
| 102 |
-
if (j < N) {
|
| 103 |
-
int k = i + 2 * a;
|
| 104 |
-
if (k < N) {
|
| 105 |
-
bool ok = (H[j] == a && H[k] == 2 * a) ||
|
| 106 |
-
(H[j] == 2 * a && H[k] == a);
|
| 107 |
-
if (ok) ++equal_cnt;
|
| 108 |
-
}
|
| 109 |
-
}
|
| 110 |
-
|
| 111 |
-
// case 2 : distance = 2a (i → j (a) → k (2a), but we treat a = H[i]/2)
|
| 112 |
-
if (a % 2 == 0) {
|
| 113 |
-
int a2 = a / 2;
|
| 114 |
-
if (a2 > 0) {
|
| 115 |
-
j = i + a2;
|
| 116 |
-
int k = i + a; // i + 2*a2 = i + a
|
| 117 |
-
if (j < N && k < N) {
|
| 118 |
-
if (H[j] == a2 && H[k] == a2) ++equal_cnt;
|
| 119 |
-
}
|
| 120 |
-
}
|
| 121 |
-
}
|
| 122 |
-
}
|
| 123 |
-
|
| 124 |
-
return total - equal_cnt;
|
| 125 |
-
}
|
| 126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/triples-part2-subtask1.cpp
DELETED
|
@@ -1,141 +0,0 @@
|
|
| 1 |
-
#include <algorithm>
|
| 2 |
-
#include <array>
|
| 3 |
-
#include <cassert>
|
| 4 |
-
#include <random>
|
| 5 |
-
#include <vector>
|
| 6 |
-
|
| 7 |
-
/* ----------------------------------------------------------------------
|
| 8 |
-
Helper type – a triple together with the *sorted* list of its three
|
| 9 |
-
distances (d1 , d2 , d3). The distances are stored already sorted so
|
| 10 |
-
we can compare them directly with the sorted heights of the same
|
| 11 |
-
triple.
|
| 12 |
-
---------------------------------------------------------------------- */
|
| 13 |
-
struct Triple
|
| 14 |
-
{
|
| 15 |
-
int i{}, j{}, k{}; // indices i<j<k
|
| 16 |
-
std::array<int, 3> ds{}; // sorted distances (d1,d2,d3)
|
| 17 |
-
|
| 18 |
-
Triple(int a, int b, int c) : i(a), j(b), k(c)
|
| 19 |
-
{
|
| 20 |
-
int d1 = j - i;
|
| 21 |
-
int d2 = k - j;
|
| 22 |
-
int d3 = k - i;
|
| 23 |
-
ds = { d1, d2, d3 };
|
| 24 |
-
std::sort(ds.begin(), ds.end()); // make it sorted (ds[0] ≤ ds[1] ≤ ds[2])
|
| 25 |
-
}
|
| 26 |
-
};
|
| 27 |
-
|
| 28 |
-
/* ----------------------------------------------------------------------
|
| 29 |
-
Count how many triples are *mythical* for a given height vector H.
|
| 30 |
-
A triple is mythical iff the three heights (sorted) are exactly the
|
| 31 |
-
three distances (also sorted) of that triple.
|
| 32 |
-
---------------------------------------------------------------------- */
|
| 33 |
-
static int countTriples(const std::vector<int>& H,
|
| 34 |
-
const std::vector<Triple>& triples)
|
| 35 |
-
{
|
| 36 |
-
int cnt = 0;
|
| 37 |
-
for (const auto& tr : triples)
|
| 38 |
-
{
|
| 39 |
-
std::array<int,3> hs = { H[tr.i], H[tr.j], H[tr.k] };
|
| 40 |
-
std::sort(hs.begin(), hs.end());
|
| 41 |
-
|
| 42 |
-
if (hs == tr.ds) ++cnt;
|
| 43 |
-
}
|
| 44 |
-
return cnt;
|
| 45 |
-
}
|
| 46 |
-
|
| 47 |
-
std::vector<int> construct_range(int M, int K)
|
| 48 |
-
{
|
| 49 |
-
/* ---- 1. pre‑compute all triples for N = max(3,M) ----------------- */
|
| 50 |
-
const int N = std::max(3, M);
|
| 51 |
-
std::vector<Triple> triples;
|
| 52 |
-
triples.reserve(N * (N-1) * (N-2) / 6); // upper bound for #triples
|
| 53 |
-
|
| 54 |
-
for (int i = 0; i < N; ++i)
|
| 55 |
-
for (int j = i + 1; j < N; ++j)
|
| 56 |
-
for (int k = j + 1; k < N; ++k)
|
| 57 |
-
triples.emplace_back(i, j, k);
|
| 58 |
-
|
| 59 |
-
/* ---- 2. random search ------------------------------------------------ */
|
| 60 |
-
std::mt19937 rng{ std::random_device{}() };
|
| 61 |
-
|
| 62 |
-
// distribution for the initial random heights: 1 … N‑1 (inclusive)
|
| 63 |
-
std::uniform_int_distribution<int> initDist(1, N - 1);
|
| 64 |
-
|
| 65 |
-
// same distribution we will use when we need a random element of `ds`
|
| 66 |
-
// (the distances themselves are already in the range 1 … N‑1)
|
| 67 |
-
// No extra work required – we simply shuffle the three already‑present
|
| 68 |
-
// numbers.
|
| 69 |
-
|
| 70 |
-
int best_cnt = -1;
|
| 71 |
-
std::vector<int> best_H;
|
| 72 |
-
|
| 73 |
-
const int max_restarts = 5;
|
| 74 |
-
const int max_moves = 20000; // moves per restart
|
| 75 |
-
|
| 76 |
-
for (int restart = 0; restart < max_restarts; ++restart)
|
| 77 |
-
{
|
| 78 |
-
/* ---- a) random initial configuration --------------------------- */
|
| 79 |
-
std::vector<int> cur_H(N);
|
| 80 |
-
for (int i = 0; i < N; ++i)
|
| 81 |
-
cur_H[i] = initDist(rng);
|
| 82 |
-
|
| 83 |
-
int cur_cnt = countTriples(cur_H, triples);
|
| 84 |
-
|
| 85 |
-
if (cur_cnt > best_cnt)
|
| 86 |
-
{
|
| 87 |
-
best_cnt = cur_cnt;
|
| 88 |
-
best_H = cur_H;
|
| 89 |
-
}
|
| 90 |
-
if (cur_cnt >= K)
|
| 91 |
-
return cur_H; // we already hit the target
|
| 92 |
-
|
| 93 |
-
/* ---- b) local hill‑climbing / random‑move phase ----------------- */
|
| 94 |
-
std::vector<int> cur = cur_H; // we will mutate this copy
|
| 95 |
-
|
| 96 |
-
for (int move = 0; move < max_moves; ++move)
|
| 97 |
-
{
|
| 98 |
-
// pick a random triple
|
| 99 |
-
const Triple& tr = triples[ std::uniform_int_distribution<int>(0, triples.size() - 1)(rng) ];
|
| 100 |
-
|
| 101 |
-
// remember the old three heights (so we can revert)
|
| 102 |
-
int old_i = cur[tr.i];
|
| 103 |
-
int old_j = cur[tr.j];
|
| 104 |
-
int old_k = cur[tr.k];
|
| 105 |
-
|
| 106 |
-
// permute the three distances of this triple
|
| 107 |
-
std::array<int,3> dlist = tr.ds; // copy
|
| 108 |
-
std::shuffle(dlist.begin(), dlist.end(), rng);
|
| 109 |
-
|
| 110 |
-
// apply the move
|
| 111 |
-
cur[tr.i] = dlist[0];
|
| 112 |
-
cur[tr.j] = dlist[1];
|
| 113 |
-
cur[tr.k] = dlist[2];
|
| 114 |
-
|
| 115 |
-
int new_cnt = countTriples(cur, triples);
|
| 116 |
-
|
| 117 |
-
// accept the move only if it does not make the global count worse
|
| 118 |
-
if (new_cnt >= cur_cnt)
|
| 119 |
-
{
|
| 120 |
-
cur_cnt = new_cnt;
|
| 121 |
-
if (cur_cnt > best_cnt)
|
| 122 |
-
{
|
| 123 |
-
best_cnt = cur_cnt;
|
| 124 |
-
best_H = cur;
|
| 125 |
-
}
|
| 126 |
-
if (cur_cnt >= K)
|
| 127 |
-
return cur; // success – we reached K
|
| 128 |
-
}
|
| 129 |
-
else
|
| 130 |
-
{
|
| 131 |
-
// revert the move (the triple must be mythical again)
|
| 132 |
-
cur[tr.i] = old_i;
|
| 133 |
-
cur[tr.j] = old_j;
|
| 134 |
-
cur[tr.k] = old_k;
|
| 135 |
-
}
|
| 136 |
-
} // end of one restart's move loop
|
| 137 |
-
} // end of all restarts
|
| 138 |
-
|
| 139 |
-
// never reached K – return the best we ever found (it is still a legal vector)
|
| 140 |
-
return best_H;
|
| 141 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/triples-part2-subtask2.cpp
DELETED
|
@@ -1,358 +0,0 @@
|
|
| 1 |
-
#include <bits/stdc++.h>
|
| 2 |
-
|
| 3 |
-
using namespace std;
|
| 4 |
-
|
| 5 |
-
long long count_triples(vector<int> H)
|
| 6 |
-
{
|
| 7 |
-
const int N = static_cast<int>(H.size());
|
| 8 |
-
|
| 9 |
-
long long cnt1 = 0, cnt2 = 0, cnt3 = 0, cnt4 = 0,
|
| 10 |
-
cnt5 = 0, cnt6 = 0, equal_cnt = 0;
|
| 11 |
-
|
| 12 |
-
/* ---------- assignment 1 ---------- */
|
| 13 |
-
for (int i = 0; i < N; ++i) {
|
| 14 |
-
int j = i + H[i];
|
| 15 |
-
if (j >= N) continue;
|
| 16 |
-
int b = H[j];
|
| 17 |
-
int k = j + b;
|
| 18 |
-
if (k >= N) continue;
|
| 19 |
-
if (H[k] == H[i] + b) ++cnt1;
|
| 20 |
-
}
|
| 21 |
-
|
| 22 |
-
/* ---------- assignment 2 ---------- */
|
| 23 |
-
for (int i = 0; i < N; ++i) {
|
| 24 |
-
int j = i + H[i];
|
| 25 |
-
if (j >= N) continue;
|
| 26 |
-
int b = H[j] - H[i];
|
| 27 |
-
if (b <= 0) continue;
|
| 28 |
-
int k = j + b;
|
| 29 |
-
if (k >= N) continue;
|
| 30 |
-
if (H[k] == b) ++cnt2;
|
| 31 |
-
}
|
| 32 |
-
|
| 33 |
-
/* ---------- assignment 3 ---------- */
|
| 34 |
-
for (int j = 0; j < N; ++j) {
|
| 35 |
-
int i = j - H[j];
|
| 36 |
-
if (i < 0) continue;
|
| 37 |
-
int b = H[i];
|
| 38 |
-
int k = j + b;
|
| 39 |
-
if (k >= N) continue;
|
| 40 |
-
if (H[k] == H[j] + b) ++cnt3;
|
| 41 |
-
}
|
| 42 |
-
|
| 43 |
-
/* ---------- assignment 5 ---------- */
|
| 44 |
-
for (int j = 0; j < N; ++j) {
|
| 45 |
-
int i = j - H[j];
|
| 46 |
-
if (i < 0) continue;
|
| 47 |
-
int b = H[i] - H[j];
|
| 48 |
-
if (b <= 0) continue;
|
| 49 |
-
int k = j + b;
|
| 50 |
-
if (k >= N) continue;
|
| 51 |
-
if (H[k] == b) ++cnt5;
|
| 52 |
-
}
|
| 53 |
-
|
| 54 |
-
/* ---------- assignment 6 ---------- */
|
| 55 |
-
for (int j = 0; j < N; ++j) {
|
| 56 |
-
int k = j + H[j];
|
| 57 |
-
if (k >= N) continue;
|
| 58 |
-
int a = H[k];
|
| 59 |
-
int i = j - a;
|
| 60 |
-
if (i < 0) continue;
|
| 61 |
-
if (H[i] == a + H[j]) ++cnt6;
|
| 62 |
-
}
|
| 63 |
-
|
| 64 |
-
/* ---------- assignment 4 (group i+H[i] = k-H[k]) ---------- */
|
| 65 |
-
// groups[T] = list of k such that k - H[k] == T (T = “key”)
|
| 66 |
-
unordered_map<int, vector<int>> groups;
|
| 67 |
-
groups.reserve(N * 2);
|
| 68 |
-
for (int k = 0; k < N; ++k) {
|
| 69 |
-
int T = k - H[k];
|
| 70 |
-
groups[T].push_back(k); // k grows, so each vector stays sorted
|
| 71 |
-
}
|
| 72 |
-
|
| 73 |
-
for (int i = 0; i < N; ++i) {
|
| 74 |
-
int T = i + H[i];
|
| 75 |
-
auto it = groups.find(T);
|
| 76 |
-
if (it == groups.end()) continue; // no k with the needed key
|
| 77 |
-
|
| 78 |
-
const vector<int>& ks = it->second;
|
| 79 |
-
// first k that is > i
|
| 80 |
-
auto posIter = upper_bound(ks.begin(), ks.end(), i);
|
| 81 |
-
int H_i = H[i];
|
| 82 |
-
|
| 83 |
-
for (auto kIt = posIter; kIt != ks.end(); ++kIt) {
|
| 84 |
-
int k = *kIt;
|
| 85 |
-
int j = k - H_i;
|
| 86 |
-
if (j >= N) break; // larger k → larger j, so we can stop
|
| 87 |
-
// i < j < k holds automatically for the chosen ks
|
| 88 |
-
if (H[j] == k - i) ++cnt4;
|
| 89 |
-
}
|
| 90 |
-
}
|
| 91 |
-
|
| 92 |
-
long long total = cnt1 + cnt2 + cnt3 + cnt4 + cnt5 + cnt6;
|
| 93 |
-
|
| 94 |
-
/* ---------- triples with equal distances (a = b) ----------
|
| 95 |
-
These triples were counted twice (once in the main total and
|
| 96 |
-
once in the equal‑distance special case), therefore we subtract
|
| 97 |
-
them once at the end. */
|
| 98 |
-
for (int i = 0; i < N; ++i) {
|
| 99 |
-
int a = H[i];
|
| 100 |
-
|
| 101 |
-
// case 1 : distance = a (i → j → k, with j = i+a, k = i+2a)
|
| 102 |
-
int j = i + a;
|
| 103 |
-
if (j < N) {
|
| 104 |
-
int k = i + 2 * a;
|
| 105 |
-
if (k < N) {
|
| 106 |
-
bool ok = (H[j] == a && H[k] == 2 * a) ||
|
| 107 |
-
(H[j] == 2 * a && H[k] == a);
|
| 108 |
-
if (ok) ++equal_cnt;
|
| 109 |
-
}
|
| 110 |
-
}
|
| 111 |
-
|
| 112 |
-
// case 2 : distance = 2a (i → j (a) → k (2a), but we treat a = H[i]/2)
|
| 113 |
-
if (a % 2 == 0) {
|
| 114 |
-
int a2 = a / 2;
|
| 115 |
-
if (a2 > 0) {
|
| 116 |
-
j = i + a2;
|
| 117 |
-
int k = i + a; // i + 2*a2 = i + a
|
| 118 |
-
if (j < N && k < N) {
|
| 119 |
-
if (H[j] == a2 && H[k] == a2) ++equal_cnt;
|
| 120 |
-
}
|
| 121 |
-
}
|
| 122 |
-
}
|
| 123 |
-
}
|
| 124 |
-
|
| 125 |
-
return total - equal_cnt;
|
| 126 |
-
}
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
/* -------------------------------------------------------------
|
| 131 |
-
2. greedy_builder – builds a candidate array from (h0,h1)
|
| 132 |
-
------------------------------------------------------------- */
|
| 133 |
-
static vector<int> greedy_builder(int N, int h0, int h1,
|
| 134 |
-
int D, int max_h)
|
| 135 |
-
{
|
| 136 |
-
vector<int> H(N, 1);
|
| 137 |
-
H[0] = h0;
|
| 138 |
-
H[1] = h1;
|
| 139 |
-
|
| 140 |
-
vector<int> cnt(max_h + 1, 0);
|
| 141 |
-
vector<int> last(max_h + 1, 0);
|
| 142 |
-
int version = 0;
|
| 143 |
-
const int twoD = 2 * D;
|
| 144 |
-
|
| 145 |
-
for (int k = 2; k < N; ++k) {
|
| 146 |
-
++version;
|
| 147 |
-
int best_cnt = 0;
|
| 148 |
-
int best_missing = 1;
|
| 149 |
-
int i_start = k - twoD;
|
| 150 |
-
if (i_start < 0) i_start = 0;
|
| 151 |
-
|
| 152 |
-
for (int i = i_start; i < k; ++i) {
|
| 153 |
-
int hi = H[i];
|
| 154 |
-
int s = k - i;
|
| 155 |
-
if (hi >= s) continue;
|
| 156 |
-
|
| 157 |
-
// ----- left candidate j = i + hi -----
|
| 158 |
-
int j = i + hi;
|
| 159 |
-
if (j < k) {
|
| 160 |
-
int a = hi;
|
| 161 |
-
int b = s - hi;
|
| 162 |
-
int hj = H[j];
|
| 163 |
-
bool ok = (hj == a || hj == b || hj == s) &&
|
| 164 |
-
!(a != b && hi == hj);
|
| 165 |
-
if (ok) {
|
| 166 |
-
int missing = 2 * s - hi - hj;
|
| 167 |
-
if (1 <= missing && missing <= max_h) {
|
| 168 |
-
if (last[missing] != version) {
|
| 169 |
-
cnt[missing] = 1;
|
| 170 |
-
last[missing] = version;
|
| 171 |
-
} else {
|
| 172 |
-
++cnt[missing];
|
| 173 |
-
}
|
| 174 |
-
if (cnt[missing] > best_cnt) {
|
| 175 |
-
best_cnt = cnt[missing];
|
| 176 |
-
best_missing = missing;
|
| 177 |
-
}
|
| 178 |
-
}
|
| 179 |
-
}
|
| 180 |
-
}
|
| 181 |
-
|
| 182 |
-
// ----- right candidate j2 = k - hi -----
|
| 183 |
-
int j2 = k - hi;
|
| 184 |
-
if (j2 > i && j2 != i + hi) {
|
| 185 |
-
int a = s - hi;
|
| 186 |
-
int b = hi;
|
| 187 |
-
int hj = H[j2];
|
| 188 |
-
bool ok = (hj == a || hj == b || hj == s) &&
|
| 189 |
-
!(a != b && hi == hj);
|
| 190 |
-
if (ok) {
|
| 191 |
-
int missing = 2 * s - hi - hj;
|
| 192 |
-
if (1 <= missing && missing <= max_h) {
|
| 193 |
-
if (last[missing] != version) {
|
| 194 |
-
cnt[missing] = 1;
|
| 195 |
-
last[missing] = version;
|
| 196 |
-
} else {
|
| 197 |
-
++cnt[missing];
|
| 198 |
-
}
|
| 199 |
-
if (cnt[missing] > best_cnt) {
|
| 200 |
-
best_cnt = cnt[missing];
|
| 201 |
-
best_missing = missing;
|
| 202 |
-
}
|
| 203 |
-
}
|
| 204 |
-
}
|
| 205 |
-
}
|
| 206 |
-
}
|
| 207 |
-
|
| 208 |
-
H[k] = (best_cnt > 0) ? best_missing : 1;
|
| 209 |
-
}
|
| 210 |
-
return H;
|
| 211 |
-
}
|
| 212 |
-
|
| 213 |
-
/* -------------------------------------------------------------
|
| 214 |
-
3. construct_range – the whole construction routine
|
| 215 |
-
------------------------------------------------------------- */
|
| 216 |
-
vector<int> construct_range(int M, int K)
|
| 217 |
-
{
|
| 218 |
-
const int N = max(3, M); // we always use exactly N = M (M>=3 in tests)
|
| 219 |
-
const int max_h = N - 1;
|
| 220 |
-
int D = (N - 1) / 2;
|
| 221 |
-
if (D == 0) D = 1;
|
| 222 |
-
|
| 223 |
-
long long best_T = -1;
|
| 224 |
-
vector<int> best_H;
|
| 225 |
-
|
| 226 |
-
/* ----- helper: evaluate a candidate and keep the best one ----- */
|
| 227 |
-
auto evaluate = [&](const vector<int>& H) {
|
| 228 |
-
long long T = count_triples(H);
|
| 229 |
-
if (T > best_T) {
|
| 230 |
-
best_T = T;
|
| 231 |
-
best_H = H;
|
| 232 |
-
if (best_T >= K) throw runtime_error("enough triples");
|
| 233 |
-
}
|
| 234 |
-
};
|
| 235 |
-
|
| 236 |
-
/* ----- deterministic patterns ----- */
|
| 237 |
-
auto add_pattern = [&](const vector<int>& pat) {
|
| 238 |
-
int repeats = N / static_cast<int>(pat.size()) + 1;
|
| 239 |
-
vector<int> H;
|
| 240 |
-
H.reserve(N);
|
| 241 |
-
for (int i = 0; i < repeats; ++i) H.insert(H.end(), pat.begin(), pat.end());
|
| 242 |
-
H.resize(N);
|
| 243 |
-
evaluate(H);
|
| 244 |
-
};
|
| 245 |
-
|
| 246 |
-
add_pattern({1, 1, 2});
|
| 247 |
-
add_pattern({1, 2, 1});
|
| 248 |
-
add_pattern({2, 1, 1});
|
| 249 |
-
|
| 250 |
-
// a2 pattern – 4 on positions whose block‑index %3 ==0
|
| 251 |
-
vector<int> H(N);
|
| 252 |
-
for (int i = 0; i < N; ++i) {
|
| 253 |
-
if (i % 2 == 0) { // even index
|
| 254 |
-
int pos = i / 2;
|
| 255 |
-
H[i] = (pos % 3 == 0) ? 4 : 2;
|
| 256 |
-
} else { // odd index
|
| 257 |
-
int pos = (i - 1) / 2;
|
| 258 |
-
H[i] = (pos % 3 == 0) ? 4 : 2;
|
| 259 |
-
}
|
| 260 |
-
}
|
| 261 |
-
evaluate(H);
|
| 262 |
-
|
| 263 |
-
/* ----- start pairs for the greedy builder ----- */
|
| 264 |
-
unordered_set<long long> start_pairs; // encode pair (h0,h1) in a 64‑bit key
|
| 265 |
-
auto encode = [&](int a, int b) -> long long { return (static_cast<long long>(a) << 32) | static_cast<unsigned int>(b); };
|
| 266 |
-
|
| 267 |
-
int limit = min(20, max_h);
|
| 268 |
-
for (int h0 = 1; h0 <= limit; ++h0)
|
| 269 |
-
for (int h1 = 1; h1 <= limit; ++h1)
|
| 270 |
-
start_pairs.insert(encode(h0, h1));
|
| 271 |
-
|
| 272 |
-
start_pairs.insert(encode(max_h, max_h));
|
| 273 |
-
start_pairs.insert(encode(max_h, 1));
|
| 274 |
-
start_pairs.insert(encode(1, max_h));
|
| 275 |
-
if (max_h >= 2) {
|
| 276 |
-
start_pairs.insert(encode(max_h - 1, max_h - 1));
|
| 277 |
-
start_pairs.insert(encode(max_h - 2, max_h - 2));
|
| 278 |
-
}
|
| 279 |
-
|
| 280 |
-
mt19937_64 rnd(123456789ULL);
|
| 281 |
-
for (int i = 0; i < 30; ++i) {
|
| 282 |
-
int h0 = uniform_int_distribution<int>(1, max_h)(rnd);
|
| 283 |
-
int h1 = uniform_int_distribution<int>(1, max_h)(rnd);
|
| 284 |
-
start_pairs.insert(encode(h0, h1));
|
| 285 |
-
}
|
| 286 |
-
|
| 287 |
-
vector<pair<int,int>> start_list;
|
| 288 |
-
start_list.reserve(start_pairs.size());
|
| 289 |
-
for (auto key : start_pairs) {
|
| 290 |
-
int h0 = static_cast<int>(key >> 32);
|
| 291 |
-
int h1 = static_cast<int>(key & 0xffffffff);
|
| 292 |
-
start_list.emplace_back(h0, h1);
|
| 293 |
-
}
|
| 294 |
-
shuffle(start_list.begin(), start_list.end(),
|
| 295 |
-
mt19937_64(987654321ULL));
|
| 296 |
-
|
| 297 |
-
/* ----- greedy builder for every start pair ----- */
|
| 298 |
-
try {
|
| 299 |
-
for (auto [h0, h1] : start_list) {
|
| 300 |
-
int h0c = max(1, min(max_h, h0));
|
| 301 |
-
int h1c = max(1, min(max_h, h1));
|
| 302 |
-
vector<int> cand = greedy_builder(N, h0c, h1c, D, max_h);
|
| 303 |
-
evaluate(cand);
|
| 304 |
-
}
|
| 305 |
-
} catch (const runtime_error&) {
|
| 306 |
-
// we already hit K – just keep the current best
|
| 307 |
-
}
|
| 308 |
-
|
| 309 |
-
/* ----- hill climbing if needed ----- */
|
| 310 |
-
if (best_T < K) {
|
| 311 |
-
vector<int> cur_H = best_H;
|
| 312 |
-
long long cur_T = best_T;
|
| 313 |
-
|
| 314 |
-
// values we are allowed to change to (small numbers + the maximal one)
|
| 315 |
-
vector<int> cand_vals;
|
| 316 |
-
int small_limit = min(N, 30);
|
| 317 |
-
for (int v = 1; v <= small_limit; ++v) cand_vals.push_back(v);
|
| 318 |
-
if (max_h > small_limit) cand_vals.push_back(max_h);
|
| 319 |
-
sort(cand_vals.begin(), cand_vals.end());
|
| 320 |
-
cand_vals.erase(unique(cand_vals.begin(), cand_vals.end()), cand_vals.end());
|
| 321 |
-
|
| 322 |
-
mt19937_64 rnd_hc(987654321ULL);
|
| 323 |
-
uniform_int_distribution<int> idx_dist(0, N - 1);
|
| 324 |
-
uniform_int_distribution<int> val_dist(0, static_cast<int>(cand_vals.size()) - 1);
|
| 325 |
-
|
| 326 |
-
for (int step = 0; step < 20000 && best_T < K; ++step) {
|
| 327 |
-
int i = idx_dist(rnd_hc);
|
| 328 |
-
int new_val = cand_vals[val_dist(rnd_hc)];
|
| 329 |
-
if (new_val == cur_H[i]) continue;
|
| 330 |
-
|
| 331 |
-
int old = cur_H[i];
|
| 332 |
-
cur_H[i] = new_val;
|
| 333 |
-
long long new_T = count_triples(cur_H);
|
| 334 |
-
if (new_T > cur_T) {
|
| 335 |
-
cur_T = new_T;
|
| 336 |
-
if (new_T > best_T) {
|
| 337 |
-
best_T = new_T;
|
| 338 |
-
best_H = cur_H;
|
| 339 |
-
if (best_T >= K) break;
|
| 340 |
-
}
|
| 341 |
-
} else {
|
| 342 |
-
cur_H[i] = old; // revert
|
| 343 |
-
}
|
| 344 |
-
}
|
| 345 |
-
}
|
| 346 |
-
|
| 347 |
-
/* ----- final safety clamp ----- */
|
| 348 |
-
vector<int> out_H(N);
|
| 349 |
-
for (int i = 0; i < N; ++i) {
|
| 350 |
-
int v = best_H[i];
|
| 351 |
-
if (v < 1) v = 1;
|
| 352 |
-
if (v > max_h) v = max_h;
|
| 353 |
-
out_H[i] = v;
|
| 354 |
-
}
|
| 355 |
-
out_H.resize(N);
|
| 356 |
-
return out_H;
|
| 357 |
-
}
|
| 358 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/triples-part2-subtask3.cpp
DELETED
|
@@ -1,196 +0,0 @@
|
|
| 1 |
-
#include <algorithm>
|
| 2 |
-
#include <cassert>
|
| 3 |
-
#include <random>
|
| 4 |
-
#include <utility>
|
| 5 |
-
#include <vector>
|
| 6 |
-
#include <cstdint>
|
| 7 |
-
#include <unordered_map>
|
| 8 |
-
|
| 9 |
-
/* ------------------------------------------------------------------ */
|
| 10 |
-
/* Helper that implements the “greedy builder”. */
|
| 11 |
-
/* It returns both the constructed height vector H and the total T. */
|
| 12 |
-
/* ------------------------------------------------------------------ */
|
| 13 |
-
static std::pair<std::vector<int>, long long>
|
| 14 |
-
greedy_builder(int N,
|
| 15 |
-
int h0,
|
| 16 |
-
int h1,
|
| 17 |
-
const std::vector<int>& useful_vals,
|
| 18 |
-
std::mt19937& rng)
|
| 19 |
-
{
|
| 20 |
-
std::vector<int> H(N, 0);
|
| 21 |
-
H[0] = h0;
|
| 22 |
-
H[1] = h1;
|
| 23 |
-
|
| 24 |
-
const int max_missing = N - 1; // allowed values are 1 … max_missing
|
| 25 |
-
std::vector<int> cnt(max_missing + 1, 0);
|
| 26 |
-
std::vector<int> last(max_missing + 1, 0);
|
| 27 |
-
|
| 28 |
-
long long total_T = 0; // may be larger than int
|
| 29 |
-
const int D = (N - 1) / 2;
|
| 30 |
-
const int twoD = 2 * D;
|
| 31 |
-
|
| 32 |
-
int version = 0; // increased for every k
|
| 33 |
-
|
| 34 |
-
for (int k = 2; k < N; ++k) {
|
| 35 |
-
++version; // new “run” for this k
|
| 36 |
-
|
| 37 |
-
int best_cnt = 0; // best counter for this k
|
| 38 |
-
int best_missing = 1; // associated missing value
|
| 39 |
-
|
| 40 |
-
int i_start = k - twoD;
|
| 41 |
-
if (i_start < 0) i_start = 0;
|
| 42 |
-
|
| 43 |
-
for (int i = i_start; i < k; ++i) {
|
| 44 |
-
int hi = H[i];
|
| 45 |
-
int s = k - i; // s = k-i > 0
|
| 46 |
-
|
| 47 |
-
if (hi >= s) continue; // no candidate possible
|
| 48 |
-
|
| 49 |
-
/* ---------- left distance candidate j = i + hi ---------- */
|
| 50 |
-
int j = i + hi;
|
| 51 |
-
if (j < k) {
|
| 52 |
-
int a = hi;
|
| 53 |
-
int b = s - hi; // the two distances that must appear together
|
| 54 |
-
int hj = H[j];
|
| 55 |
-
if (hj == a || hj == b || hj == s) {
|
| 56 |
-
if (! (a != b && hi == hj)) { // the “not (a!=b && hi==hj)” guard
|
| 57 |
-
int missing = 2 * s - hi - hj;
|
| 58 |
-
if (1 <= missing && missing <= max_missing) {
|
| 59 |
-
if (last[missing] != version) {
|
| 60 |
-
cnt[missing] = 1;
|
| 61 |
-
last[missing] = version;
|
| 62 |
-
} else {
|
| 63 |
-
++cnt[missing];
|
| 64 |
-
}
|
| 65 |
-
int cur = cnt[missing];
|
| 66 |
-
if (cur > best_cnt) {
|
| 67 |
-
best_cnt = cur;
|
| 68 |
-
best_missing = missing;
|
| 69 |
-
}
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
}
|
| 73 |
-
}
|
| 74 |
-
|
| 75 |
-
/* ---------- right distance candidate j = k - hi ---------- */
|
| 76 |
-
j = k - hi; // right‑hand candidate, must be > i and not the same as left one
|
| 77 |
-
if (j > i && j != i + hi) {
|
| 78 |
-
int a = s - hi;
|
| 79 |
-
int b = hi;
|
| 80 |
-
int hj = H[j];
|
| 81 |
-
if (hj == a || hj == b || hj == s) {
|
| 82 |
-
if (! (a != b && hi == hj)) {
|
| 83 |
-
int missing = 2 * s - hi - hj;
|
| 84 |
-
if (1 <= missing && missing <= max_missing) {
|
| 85 |
-
if (last[missing] != version) {
|
| 86 |
-
cnt[missing] = 1;
|
| 87 |
-
last[missing] = version;
|
| 88 |
-
} else {
|
| 89 |
-
++cnt[missing];
|
| 90 |
-
}
|
| 91 |
-
int cur = cnt[missing];
|
| 92 |
-
if (cur > best_cnt) {
|
| 93 |
-
best_cnt = cur;
|
| 94 |
-
best_missing = missing;
|
| 95 |
-
}
|
| 96 |
-
}
|
| 97 |
-
}
|
| 98 |
-
}
|
| 99 |
-
}
|
| 100 |
-
} // end for i
|
| 101 |
-
|
| 102 |
-
if (best_cnt > 0) {
|
| 103 |
-
H[k] = best_missing;
|
| 104 |
-
total_T += best_cnt;
|
| 105 |
-
} else {
|
| 106 |
-
std::uniform_int_distribution<int> dist(0, static_cast<int>(useful_vals.size()) - 1);
|
| 107 |
-
H[k] = useful_vals[dist(rng)];
|
| 108 |
-
}
|
| 109 |
-
}
|
| 110 |
-
|
| 111 |
-
return {std::move(H), total_T};
|
| 112 |
-
}
|
| 113 |
-
|
| 114 |
-
/* ------------------------------------------------------------------ */
|
| 115 |
-
/* Main routine requested by the problem statement. */
|
| 116 |
-
/* ------------------------------------------------------------------ */
|
| 117 |
-
std::vector<int> construct_range(int M, int K)
|
| 118 |
-
{
|
| 119 |
-
/* ---- 1. decide N ------------------------------------------------ */
|
| 120 |
-
int N = std::max(3, M);
|
| 121 |
-
if (N > M) N = M;
|
| 122 |
-
// after this: 3 <= N <= M (or N = M when M < 3)
|
| 123 |
-
|
| 124 |
-
const int max_h = N - 1; // allowed heights are 1 … max_h
|
| 125 |
-
|
| 126 |
-
/* ---- 2. useful fallback values ---------------------------------- */
|
| 127 |
-
std::vector<int> useful_vals;
|
| 128 |
-
int limit = std::min(N, 10);
|
| 129 |
-
for (int v = 1; v <= limit; ++v) useful_vals.push_back(v);
|
| 130 |
-
if (max_h >= 1 && std::find(useful_vals.begin(), useful_vals.end(), max_h) == useful_vals.end())
|
| 131 |
-
useful_vals.push_back(max_h);
|
| 132 |
-
|
| 133 |
-
/* ---- 3. deterministic seeds -------------------------------------- */
|
| 134 |
-
std::vector<std::pair<int, int>> seeds = {
|
| 135 |
-
{1, 1}, {1, 2}, {2, 1}, {2, 2}
|
| 136 |
-
};
|
| 137 |
-
if (max_h >= 1) seeds.emplace_back(max_h, max_h);
|
| 138 |
-
if (max_h >= 2) seeds.emplace_back(max_h - 1, max_h - 1);
|
| 139 |
-
seeds.emplace_back(max_h, 1);
|
| 140 |
-
seeds.emplace_back(1, max_h);
|
| 141 |
-
|
| 142 |
-
/* ---- 4. a few random seeds (fixed RNG) -------------------------- */
|
| 143 |
-
std::mt19937 rnd(123456);
|
| 144 |
-
std::uniform_int_distribution<int> dist01(1, max_h);
|
| 145 |
-
for (int i = 0; i < 3; ++i) {
|
| 146 |
-
int h0 = dist01(rnd);
|
| 147 |
-
int h1 = dist01(rnd);
|
| 148 |
-
seeds.emplace_back(h0, h1);
|
| 149 |
-
}
|
| 150 |
-
|
| 151 |
-
/* ---- 5. deduplicate ---------------------------------------------- */
|
| 152 |
-
std::vector<std::pair<int, int>> uniq_seeds;
|
| 153 |
-
{
|
| 154 |
-
std::vector<bool> seen((max_h + 1) * (max_h + 1), false); // cheap, because max_h is at most a few thousands
|
| 155 |
-
for (auto &p : seeds) {
|
| 156 |
-
int h0 = std::max(1, std::min(max_h, p.first));
|
| 157 |
-
int h1 = std::max(1, std::min(max_h, p.second));
|
| 158 |
-
int idx = (h0 - 1) * (max_h + 1) + (h1 - 1);
|
| 159 |
-
if (!seen[idx]) {
|
| 160 |
-
seen[idx] = true;
|
| 161 |
-
uniq_seeds.emplace_back(h0, h1);
|
| 162 |
-
}
|
| 163 |
-
}
|
| 164 |
-
}
|
| 165 |
-
seeds.swap(uniq_seeds);
|
| 166 |
-
|
| 167 |
-
/* ---- 6. try every seed, keep the best one ----------------------- */
|
| 168 |
-
std::vector<int> best_H;
|
| 169 |
-
long long best_T = -1;
|
| 170 |
-
|
| 171 |
-
std::mt19937 rng(123456); // same RNG for the fallback values
|
| 172 |
-
for (const auto &seed : seeds) {
|
| 173 |
-
int h0 = std::max(1, std::min(max_h, seed.first));
|
| 174 |
-
int h1 = std::max(1, std::min(max_h, seed.second));
|
| 175 |
-
|
| 176 |
-
auto [H, T] = greedy_builder(N, h0, h1, useful_vals, rng);
|
| 177 |
-
if (T > best_T) {
|
| 178 |
-
best_T = T;
|
| 179 |
-
best_H = H; // copy
|
| 180 |
-
if (best_T >= K) break; // early exit when we already have enough
|
| 181 |
-
}
|
| 182 |
-
}
|
| 183 |
-
|
| 184 |
-
/* ---- 7. final clamping (safety) ---------------------------------- */
|
| 185 |
-
for (int &v : best_H) {
|
| 186 |
-
if (v < 1) v = 1;
|
| 187 |
-
else if (v > max_h) v = max_h;
|
| 188 |
-
}
|
| 189 |
-
|
| 190 |
-
if (static_cast<int>(best_H.size()) > N)
|
| 191 |
-
best_H.resize(N);
|
| 192 |
-
else if (static_cast<int>(best_H.size()) < N)
|
| 193 |
-
best_H.resize(N, 1); // should not happen, but just in case
|
| 194 |
-
|
| 195 |
-
return best_H;
|
| 196 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/triples-part2-subtask4.cpp
DELETED
|
@@ -1,122 +0,0 @@
|
|
| 1 |
-
#include <vector>
|
| 2 |
-
#include <algorithm> // std::min, std::max
|
| 3 |
-
|
| 4 |
-
std::vector<int> construct_range(int M, int /* K */)
|
| 5 |
-
{
|
| 6 |
-
// -----------------------------------------------------------------
|
| 7 |
-
// 1) decide the final length N and the maximal allowed height
|
| 8 |
-
// -----------------------------------------------------------------
|
| 9 |
-
int N = std::max(3, M);
|
| 10 |
-
if (N > M) // this makes N = M when M < 3
|
| 11 |
-
N = M;
|
| 12 |
-
|
| 13 |
-
int max_allowed = N - 1; // heights are in [1 .. max_allowed]
|
| 14 |
-
|
| 15 |
-
// radius of the sliding window
|
| 16 |
-
int D = std::min(3500, (N - 1) / 2);
|
| 17 |
-
int twoD = 2 * D;
|
| 18 |
-
|
| 19 |
-
// -----------------------------------------------------------------
|
| 20 |
-
// 2) data structures
|
| 21 |
-
// -----------------------------------------------------------------
|
| 22 |
-
std::vector<int> H(N, 0);
|
| 23 |
-
H[0] = 1;
|
| 24 |
-
if (N > 1)
|
| 25 |
-
H[1] = 2; // second peak gets a different height
|
| 26 |
-
|
| 27 |
-
// versioned counters for the “missing’’ height
|
| 28 |
-
std::vector<int> cnt(max_allowed + 1, 0);
|
| 29 |
-
std::vector<int> last(max_allowed + 1, 0);
|
| 30 |
-
int version = 0; // increased for every k
|
| 31 |
-
int total = 0; // lower bound on the number of triples
|
| 32 |
-
|
| 33 |
-
// -----------------------------------------------------------------
|
| 34 |
-
// 3) greedy construction
|
| 35 |
-
// -----------------------------------------------------------------
|
| 36 |
-
for (int k = 2; k < N; ++k) {
|
| 37 |
-
++version;
|
| 38 |
-
int i_start = k - twoD;
|
| 39 |
-
if (i_start < 0) i_start = 0;
|
| 40 |
-
|
| 41 |
-
int best_cnt = 0;
|
| 42 |
-
int best_missing = 1; // default if nothing is found
|
| 43 |
-
|
| 44 |
-
// scan the recent window [i_start, k)
|
| 45 |
-
for (int i = i_start; i < k; ++i) {
|
| 46 |
-
int hi = H[i];
|
| 47 |
-
int s = k - i; // distance i → k
|
| 48 |
-
if (hi >= s) continue; // cannot be used, skip
|
| 49 |
-
|
| 50 |
-
// -------------------------------------------------------------
|
| 51 |
-
// left candidate: j = i + hi
|
| 52 |
-
// -------------------------------------------------------------
|
| 53 |
-
int j = i + hi; // always < k because hi < s
|
| 54 |
-
int hj = H[j];
|
| 55 |
-
int a = hi;
|
| 56 |
-
int b = s - hi;
|
| 57 |
-
// (hj == a or hj == b or hj == s) and not (a != b && hi == hj)
|
| 58 |
-
if ((hj == a || hj == b || hj == s) &&
|
| 59 |
-
!(a != b && hi == hj)) {
|
| 60 |
-
int missing = 2 * s - hi - hj;
|
| 61 |
-
if (1 <= missing && missing <= max_allowed) {
|
| 62 |
-
if (last[missing] != version) {
|
| 63 |
-
cnt[missing] = 1;
|
| 64 |
-
last[missing] = version;
|
| 65 |
-
} else {
|
| 66 |
-
++cnt[missing];
|
| 67 |
-
}
|
| 68 |
-
int cur = cnt[missing];
|
| 69 |
-
if (cur > best_cnt) {
|
| 70 |
-
best_cnt = cur;
|
| 71 |
-
best_missing = missing;
|
| 72 |
-
}
|
| 73 |
-
}
|
| 74 |
-
}
|
| 75 |
-
|
| 76 |
-
// -------------------------------------------------------------
|
| 77 |
-
// right candidate: j2 = k - hi (different from the left one)
|
| 78 |
-
// -------------------------------------------------------------
|
| 79 |
-
int j2 = k - hi;
|
| 80 |
-
if (j2 > i && j2 != i + hi) {
|
| 81 |
-
hj = H[j2];
|
| 82 |
-
a = s - hi;
|
| 83 |
-
b = hi;
|
| 84 |
-
if ((hj == a || hj == b || hj == s) &&
|
| 85 |
-
!(a != b && hi == hj)) {
|
| 86 |
-
int missing = 2 * s - hi - hj;
|
| 87 |
-
if (1 <= missing && missing <= max_allowed) {
|
| 88 |
-
if (last[missing] != version) {
|
| 89 |
-
cnt[missing] = 1;
|
| 90 |
-
last[missing] = version;
|
| 91 |
-
} else {
|
| 92 |
-
++cnt[missing];
|
| 93 |
-
}
|
| 94 |
-
int cur = cnt[missing];
|
| 95 |
-
if (cur > best_cnt) {
|
| 96 |
-
best_cnt = cur;
|
| 97 |
-
best_missing = missing;
|
| 98 |
-
}
|
| 99 |
-
}
|
| 100 |
-
}
|
| 101 |
-
}
|
| 102 |
-
} // end for i
|
| 103 |
-
|
| 104 |
-
// choose the best missing height (or 1 if nothing helped)
|
| 105 |
-
if (best_cnt > 0) {
|
| 106 |
-
H[k] = best_missing;
|
| 107 |
-
total += best_cnt;
|
| 108 |
-
} else {
|
| 109 |
-
H[k] = 1;
|
| 110 |
-
}
|
| 111 |
-
}
|
| 112 |
-
|
| 113 |
-
// -----------------------------------------------------------------
|
| 114 |
-
// 4) safety clamp (normally already satisfied)
|
| 115 |
-
// -----------------------------------------------------------------
|
| 116 |
-
for (int &v : H) {
|
| 117 |
-
if (v < 1) v = 1;
|
| 118 |
-
else if (v > max_allowed) v = max_allowed;
|
| 119 |
-
}
|
| 120 |
-
|
| 121 |
-
return H; // the constructed range
|
| 122 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/triples-part2-subtask5.cpp
DELETED
|
@@ -1,141 +0,0 @@
|
|
| 1 |
-
#include <bits/stdc++.h>
|
| 2 |
-
using namespace std;
|
| 3 |
-
|
| 4 |
-
/* ------------------------------------------------------------
|
| 5 |
-
Greedy construction of one block
|
| 6 |
-
------------------------------------------------------------ */
|
| 7 |
-
static pair<vector<int>, long long> build_block(int B, int D)
|
| 8 |
-
{
|
| 9 |
-
/* H[0] … H[B‑1] – heights, 1 ≤ H[i] ≤ B‑1 */
|
| 10 |
-
vector<int> H(B, 0);
|
| 11 |
-
H[0] = 1;
|
| 12 |
-
H[1] = 1; // any value 1 … B‑1 would work
|
| 13 |
-
|
| 14 |
-
const int max_allowed = B - 1;
|
| 15 |
-
int max_missing = 4 * D;
|
| 16 |
-
if (max_missing > max_allowed) max_missing = max_allowed;
|
| 17 |
-
if (max_missing < 1) max_missing = 1; // at least 1
|
| 18 |
-
|
| 19 |
-
/* versioned counters for “missing” values (size = max_missing+1) */
|
| 20 |
-
vector<int> cnt(max_missing + 1, 0);
|
| 21 |
-
vector<int> last(max_missing + 1, 0);
|
| 22 |
-
int version = 0;
|
| 23 |
-
|
| 24 |
-
long long total = 0; // total number of triples created in the block
|
| 25 |
-
const int twoD = 2 * D;
|
| 26 |
-
|
| 27 |
-
for (int k = 2; k < B; ++k) {
|
| 28 |
-
++version; // start a fresh counting round for this k
|
| 29 |
-
int best_cnt = 0;
|
| 30 |
-
int best_missing = 1; // default – will be overwritten if we find a better one
|
| 31 |
-
|
| 32 |
-
/* the distance from the leftmost i we have to examine.
|
| 33 |
-
i must satisfy k‑i ≤ 2·D, i.e. i ≥ k‑2·D */
|
| 34 |
-
int i_start = k - twoD;
|
| 35 |
-
if (i_start < 0) i_start = 0;
|
| 36 |
-
|
| 37 |
-
for (int i = i_start; i < k; ++i) {
|
| 38 |
-
int hi = H[i];
|
| 39 |
-
int s = k - i; // distance i → k
|
| 40 |
-
if (hi >= s) continue; // hi must be smaller than the distance
|
| 41 |
-
|
| 42 |
-
/* ----------------------------------------------------
|
| 43 |
-
left candidate : j = i + hi (the point that would be
|
| 44 |
-
exactly hi units to the right of i)
|
| 45 |
-
---------------------------------------------------- */
|
| 46 |
-
int j = i + hi;
|
| 47 |
-
if (j < k) {
|
| 48 |
-
int a = hi;
|
| 49 |
-
int b = s - hi;
|
| 50 |
-
int hj = H[j];
|
| 51 |
-
if ( (hj == a || hj == b || hj == s) &&
|
| 52 |
-
!(a != b && hi == hj) ) // avoid the “a≠b && hi==hj” case
|
| 53 |
-
{
|
| 54 |
-
int missing = 2 * s - hi - hj; // how many triples this choice would give
|
| 55 |
-
if (1 <= missing && missing <= max_missing) {
|
| 56 |
-
if (last[missing] != version) {
|
| 57 |
-
cnt[missing] = 1;
|
| 58 |
-
last[missing] = version;
|
| 59 |
-
} else {
|
| 60 |
-
++cnt[missing];
|
| 61 |
-
}
|
| 62 |
-
if (cnt[missing] > best_cnt) {
|
| 63 |
-
best_cnt = cnt[missing];
|
| 64 |
-
best_missing = missing;
|
| 65 |
-
}
|
| 66 |
-
}
|
| 67 |
-
}
|
| 68 |
-
}
|
| 69 |
-
|
| 70 |
-
/* ----------------------------------------------------
|
| 71 |
-
right candidate : j2 = k – hi (the point that would be
|
| 72 |
-
exactly hi units to the left of k)
|
| 73 |
-
---------------------------------------------------- */
|
| 74 |
-
int j2 = k - hi;
|
| 75 |
-
if (j2 > i && j2 != i + hi) { // must be a *different* position
|
| 76 |
-
int a = s - hi;
|
| 77 |
-
int b = hi;
|
| 78 |
-
int hj = H[j2];
|
| 79 |
-
if ( (hj == a || hj == b || hj == s) &&
|
| 80 |
-
!(a != b && hi == hj) )
|
| 81 |
-
{
|
| 82 |
-
int missing = 2 * s - hi - hj;
|
| 83 |
-
if (1 <= missing && missing <= max_missing) {
|
| 84 |
-
if (last[missing] != version) {
|
| 85 |
-
cnt[missing] = 1;
|
| 86 |
-
last[missing] = version;
|
| 87 |
-
} else {
|
| 88 |
-
++cnt[missing];
|
| 89 |
-
}
|
| 90 |
-
if (cnt[missing] > best_cnt) {
|
| 91 |
-
best_cnt = cnt[missing];
|
| 92 |
-
best_missing = missing;
|
| 93 |
-
}
|
| 94 |
-
}
|
| 95 |
-
}
|
| 96 |
-
}
|
| 97 |
-
} // end for i
|
| 98 |
-
|
| 99 |
-
if (best_cnt > 0) {
|
| 100 |
-
H[k] = best_missing;
|
| 101 |
-
total += best_cnt;
|
| 102 |
-
} else {
|
| 103 |
-
H[k] = 1; // fall‑back – the smallest admissible value
|
| 104 |
-
}
|
| 105 |
-
} // end for k
|
| 106 |
-
|
| 107 |
-
return {H, total};
|
| 108 |
-
}
|
| 109 |
-
|
| 110 |
-
/* ------------------------------------------------------------
|
| 111 |
-
Whole range construction
|
| 112 |
-
------------------------------------------------------------ */
|
| 113 |
-
vector<int> construct_range(int M, int K)
|
| 114 |
-
{
|
| 115 |
-
int N = M;
|
| 116 |
-
if (N < 3) N = 3;
|
| 117 |
-
|
| 118 |
-
/* block size – a good compromise between speed and strength */
|
| 119 |
-
int B = min(N, 25000);
|
| 120 |
-
|
| 121 |
-
/* window size – large enough to create many triples but not too large */
|
| 122 |
-
int D = (B - 1) / 2;
|
| 123 |
-
if (D > 4000) D = 4000;
|
| 124 |
-
if (D == 0) D = 1;
|
| 125 |
-
|
| 126 |
-
/* Build one block and repeat it to fill the whole range */
|
| 127 |
-
auto [block, /*unused*/] = build_block(B, D);
|
| 128 |
-
|
| 129 |
-
int reps = N / B;
|
| 130 |
-
int rest = N % B;
|
| 131 |
-
|
| 132 |
-
vector<int> H;
|
| 133 |
-
H.reserve(N);
|
| 134 |
-
for (int r = 0; r < reps; ++r) H.insert(H.end(), block.begin(), block.end());
|
| 135 |
-
H.insert(H.end(), block.begin(), block.begin() + rest); // add the leftover part
|
| 136 |
-
H.resize(N); // ensure length exactly N
|
| 137 |
-
|
| 138 |
-
/* At this point every H[i] already satisfies
|
| 139 |
-
1 ≤ H[i] ≤ B‑1 ≤ N‑1, i.e. the required bounds. */
|
| 140 |
-
return H;
|
| 141 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/triples-part2-subtask6.cpp
DELETED
|
@@ -1,131 +0,0 @@
|
|
| 1 |
-
#include <vector>
|
| 2 |
-
#include <algorithm> // for std::min, std::max
|
| 3 |
-
#include <cstddef> // for std::size_t
|
| 4 |
-
#include <cassert>
|
| 5 |
-
|
| 6 |
-
static std::vector<int> greedy_block(int B, int D)
|
| 7 |
-
{
|
| 8 |
-
/* H will hold the heights for the block, 0‑based indices */
|
| 9 |
-
std::vector<int> H(B, 0);
|
| 10 |
-
|
| 11 |
-
const int max_missing = B - 1; // allowed values: 1 … max_missing
|
| 12 |
-
const int twoD = 2 * D;
|
| 13 |
-
|
| 14 |
-
/* temporary counters, version stamps and the version counter */
|
| 15 |
-
std::vector<int> cnt(max_missing + 1, 0);
|
| 16 |
-
std::vector<int> last(max_missing + 1, 0);
|
| 17 |
-
int version = 0;
|
| 18 |
-
|
| 19 |
-
for (int k = 0; k < B; ++k) {
|
| 20 |
-
++version; // start a new “window”
|
| 21 |
-
|
| 22 |
-
int i_start = k - twoD;
|
| 23 |
-
if (i_start < 0) i_start = 0;
|
| 24 |
-
|
| 25 |
-
int best_cnt = 0;
|
| 26 |
-
int best_missing = 1; // any legal value if we cannot improve
|
| 27 |
-
|
| 28 |
-
for (int i = i_start; i < k; ++i) {
|
| 29 |
-
int hi = H[i];
|
| 30 |
-
int s = k - i; // distance i → k
|
| 31 |
-
if (hi >= s) continue; // hi cannot be used
|
| 32 |
-
|
| 33 |
-
/* ----------- left side: j = i + hi -------------------------- */
|
| 34 |
-
int j = i + hi;
|
| 35 |
-
if (j < k) {
|
| 36 |
-
int hj = H[j];
|
| 37 |
-
int a = hi;
|
| 38 |
-
int b = s - hi;
|
| 39 |
-
|
| 40 |
-
bool ok = (hj == a) || (hj == b) || (hj == s);
|
| 41 |
-
ok = ok && !(a != b && hi == hj); // forbid the symmetric case
|
| 42 |
-
|
| 43 |
-
if (ok) {
|
| 44 |
-
int miss = 2 * s - hi - hj; // the “missing” value
|
| 45 |
-
if (miss >= 1 && miss <= max_missing) {
|
| 46 |
-
if (last[miss] != version) {
|
| 47 |
-
cnt[miss] = 1;
|
| 48 |
-
last[miss] = version;
|
| 49 |
-
} else {
|
| 50 |
-
++cnt[miss];
|
| 51 |
-
}
|
| 52 |
-
|
| 53 |
-
if (cnt[miss] > best_cnt) {
|
| 54 |
-
best_cnt = cnt[miss];
|
| 55 |
-
best_missing = miss;
|
| 56 |
-
}
|
| 57 |
-
}
|
| 58 |
-
}
|
| 59 |
-
}
|
| 60 |
-
|
| 61 |
-
/* ----------- right side: j = k - hi ------------------------- */
|
| 62 |
-
int j2 = k - hi;
|
| 63 |
-
if (j2 > i && j2 != i + hi) {
|
| 64 |
-
int hj = H[j2];
|
| 65 |
-
int a = s - hi;
|
| 66 |
-
int b = hi;
|
| 67 |
-
|
| 68 |
-
bool ok = (hj == a) || (hj == b) || (hj == s);
|
| 69 |
-
ok = ok && !(a != b && hi == hj); // same symmetric check
|
| 70 |
-
|
| 71 |
-
if (ok) {
|
| 72 |
-
int miss = 2 * s - hi - hj;
|
| 73 |
-
if (miss >= 1 && miss <= max_missing) {
|
| 74 |
-
if (last[miss] != version) {
|
| 75 |
-
cnt[miss] = 1;
|
| 76 |
-
last[miss] = version;
|
| 77 |
-
} else {
|
| 78 |
-
++cnt[miss];
|
| 79 |
-
}
|
| 80 |
-
|
| 81 |
-
if (cnt[miss] > best_cnt) {
|
| 82 |
-
best_cnt = cnt[miss];
|
| 83 |
-
best_missing = miss;
|
| 84 |
-
}
|
| 85 |
-
}
|
| 86 |
-
}
|
| 87 |
-
}
|
| 88 |
-
} // end of inner loop over i
|
| 89 |
-
|
| 90 |
-
/* write the height for position k */
|
| 91 |
-
if (best_cnt > 0)
|
| 92 |
-
H[k] = best_missing;
|
| 93 |
-
else
|
| 94 |
-
H[k] = 1; // any legal value is fine
|
| 95 |
-
}
|
| 96 |
-
|
| 97 |
-
return H;
|
| 98 |
-
}
|
| 99 |
-
|
| 100 |
-
/* ------------------------------------------------------------------ */
|
| 101 |
-
/* Public API – exactly the signature required by the task */
|
| 102 |
-
/* ------------------------------------------------------------------ */
|
| 103 |
-
std::vector<int> construct_range(int M, int K)
|
| 104 |
-
{
|
| 105 |
-
(void)K; // avoid unused‑parameter warning
|
| 106 |
-
|
| 107 |
-
const int N = std::max(3, M); // final length of the range
|
| 108 |
-
const int B = std::min(N, 20000); // block size (greedy works better with a limit)
|
| 109 |
-
const int D = std::min(4000, (B - 1) / 2); // half‑window size
|
| 110 |
-
|
| 111 |
-
std::vector<int> block = greedy_block(B, D);
|
| 112 |
-
|
| 113 |
-
const int repeats = N / B;
|
| 114 |
-
const int rest = N % B;
|
| 115 |
-
|
| 116 |
-
std::vector<int> H;
|
| 117 |
-
H.reserve(N);
|
| 118 |
-
for (int r = 0; r < repeats; ++r)
|
| 119 |
-
H.insert(H.end(), block.begin(), block.end());
|
| 120 |
-
H.insert(H.end(), block.begin(), block.begin() + rest); // the possible tail
|
| 121 |
-
|
| 122 |
-
/* Clamp to the allowed interval [1, N‑1] – this is a harmless safety net. */
|
| 123 |
-
const int max_allowed = N - 1;
|
| 124 |
-
for (int &v : H) {
|
| 125 |
-
if (v < 1) v = 1;
|
| 126 |
-
else if (v > max_allowed) v = max_allowed;
|
| 127 |
-
}
|
| 128 |
-
|
| 129 |
-
H.resize(N); // just in case something went wrong (should already be N)
|
| 130 |
-
return H;
|
| 131 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ioi2025/worldmap.cpp
DELETED
|
@@ -1,202 +0,0 @@
|
|
| 1 |
-
#include <bits/stdc++.h>
|
| 2 |
-
using namespace std;
|
| 3 |
-
|
| 4 |
-
/* ----------------------------------------------------------------------
|
| 5 |
-
create_map
|
| 6 |
-
---------------------------------------------------------------------- */
|
| 7 |
-
vector<vector<int>> create_map(int N, int M,
|
| 8 |
-
vector<int> A, vector<int> B)
|
| 9 |
-
{
|
| 10 |
-
/* --------------------------------------------------------------
|
| 11 |
-
0‑based adjacency matrix and list of edges
|
| 12 |
-
-------------------------------------------------------------- */
|
| 13 |
-
vector<vector<char>> adj(N, vector<char>(N, 0));
|
| 14 |
-
vector<pair<int,int>> edges;
|
| 15 |
-
edges.reserve(M);
|
| 16 |
-
|
| 17 |
-
for (int k = 0; k < M; ++k) {
|
| 18 |
-
int u = A[k] - 1; // to 0‑based
|
| 19 |
-
int v = B[k] - 1;
|
| 20 |
-
adj[u][v] = adj[v][u] = 1;
|
| 21 |
-
edges.emplace_back(u, v);
|
| 22 |
-
}
|
| 23 |
-
const int M_edges = static_cast<int>(edges.size());
|
| 24 |
-
|
| 25 |
-
/* --------------------------------------------------------------
|
| 26 |
-
edge_id[u][v] (only for u < v) → index of the edge in `edges`
|
| 27 |
-
-------------------------------------------------------------- */
|
| 28 |
-
vector<vector<int>> edge_id(N, vector<int>(N, -1));
|
| 29 |
-
for (int idx = 0; idx < M_edges; ++idx) {
|
| 30 |
-
int u = edges[idx].first;
|
| 31 |
-
int v = edges[idx].second;
|
| 32 |
-
if (u > v) swap(u, v);
|
| 33 |
-
edge_id[u][v] = idx;
|
| 34 |
-
}
|
| 35 |
-
|
| 36 |
-
/* --------------------------------------------------------------
|
| 37 |
-
neighbour_mask[i] – bit mask of colours that may be placed
|
| 38 |
-
next to a cell whose colour is i (loops + the 4‑neighbours)
|
| 39 |
-
-------------------------------------------------------------- */
|
| 40 |
-
vector<uint64_t> neighbour_mask(N, 0);
|
| 41 |
-
for (int i = 0; i < N; ++i) {
|
| 42 |
-
uint64_t mask = 1ULL << i; // the colour itself
|
| 43 |
-
for (int j = 0; j < N; ++j)
|
| 44 |
-
if (adj[i][j]) mask |= (1ULL << j);
|
| 45 |
-
neighbour_mask[i] = mask;
|
| 46 |
-
}
|
| 47 |
-
const uint64_t all_mask = (N == 64) ? ~0ULL : ((1ULL << N) - 1ULL);
|
| 48 |
-
|
| 49 |
-
/* --------------------------------------------------------------
|
| 50 |
-
board size K (smallest board that could possibly work)
|
| 51 |
-
-------------------------------------------------------------- */
|
| 52 |
-
int K0 = static_cast<int>(sqrt((double)N));
|
| 53 |
-
while (K0 * K0 < N) ++K0; // ceil(sqrt(N))
|
| 54 |
-
|
| 55 |
-
int Kedge = 0;
|
| 56 |
-
while (2 * Kedge * (Kedge - 1) < M_edges) ++Kedge;
|
| 57 |
-
|
| 58 |
-
int K = max(K0, Kedge);
|
| 59 |
-
K = max(K, 2 * N); // a bit of spare space
|
| 60 |
-
if (K > 240) K = 240; // safety cap
|
| 61 |
-
|
| 62 |
-
/* --------------------------------------------------------------
|
| 63 |
-
random generator – used for the “several random attempts”
|
| 64 |
-
-------------------------------------------------------------- */
|
| 65 |
-
std::mt19937 rng(
|
| 66 |
-
static_cast<unsigned>(chrono::steady_clock::now()
|
| 67 |
-
.time_since_epoch()
|
| 68 |
-
.count()));
|
| 69 |
-
|
| 70 |
-
const int MAX_ATTEMPTS = 500;
|
| 71 |
-
|
| 72 |
-
for (int attempt = 0; attempt < MAX_ATTEMPTS; ++attempt) {
|
| 73 |
-
/* ----- fresh board for this attempt ---------------------- */
|
| 74 |
-
vector<vector<int>> grid(K, vector<int>(K, -1));
|
| 75 |
-
uint64_t used_colours = 0; // bit mask of colours already used
|
| 76 |
-
vector<char> covered(M_edges, 0);
|
| 77 |
-
int covered_cnt = 0;
|
| 78 |
-
bool ok = true;
|
| 79 |
-
|
| 80 |
-
/* ----- greedy filling of the K×K board ------------------- */
|
| 81 |
-
for (int i = 0; i < K && ok; ++i) {
|
| 82 |
-
for (int j = 0; j < K; ++j) {
|
| 83 |
-
uint64_t allowed = all_mask; // colours allowed by neighbours
|
| 84 |
-
|
| 85 |
-
if (i > 0) {
|
| 86 |
-
int top = grid[i-1][j];
|
| 87 |
-
allowed &= neighbour_mask[top];
|
| 88 |
-
}
|
| 89 |
-
if (j > 0) {
|
| 90 |
-
int left = grid[i][j-1];
|
| 91 |
-
allowed &= neighbour_mask[left];
|
| 92 |
-
}
|
| 93 |
-
|
| 94 |
-
if (allowed == 0) { // dead end → restart whole board
|
| 95 |
-
ok = false;
|
| 96 |
-
break;
|
| 97 |
-
}
|
| 98 |
-
|
| 99 |
-
uint64_t missing = all_mask & ~used_colours;
|
| 100 |
-
uint64_t missing_allowed = allowed & missing;
|
| 101 |
-
|
| 102 |
-
/* ----- pick the colour with the best gain ---------- */
|
| 103 |
-
int best_gain = -1;
|
| 104 |
-
vector<int> candidates;
|
| 105 |
-
|
| 106 |
-
uint64_t mask = allowed;
|
| 107 |
-
while (mask) {
|
| 108 |
-
uint64_t lsb = mask & -mask;
|
| 109 |
-
int c = __builtin_ctzll(lsb); // colour index (0‑based)
|
| 110 |
-
mask ^= lsb;
|
| 111 |
-
|
| 112 |
-
int gain = 0;
|
| 113 |
-
|
| 114 |
-
/* edges that would become covered if we use colour c */
|
| 115 |
-
if (i > 0) {
|
| 116 |
-
int nt = grid[i-1][j];
|
| 117 |
-
if (nt != c && adj[nt][c]) {
|
| 118 |
-
int u = min(nt, c), v = max(nt, c);
|
| 119 |
-
int eid = edge_id[u][v];
|
| 120 |
-
if (eid != -1 && !covered[eid]) ++gain;
|
| 121 |
-
}
|
| 122 |
-
}
|
| 123 |
-
if (j > 0) {
|
| 124 |
-
int nl = grid[i][j-1];
|
| 125 |
-
if (nl != c && adj[nl][c]) {
|
| 126 |
-
int u = min(nl, c), v = max(nl, c);
|
| 127 |
-
int eid = edge_id[u][v];
|
| 128 |
-
if (eid != -1 && !covered[eid]) ++gain;
|
| 129 |
-
}
|
| 130 |
-
}
|
| 131 |
-
|
| 132 |
-
/* huge bonus for a colour that has never been used */
|
| 133 |
-
if (missing_allowed && ( (1ULL << c) & missing_allowed ))
|
| 134 |
-
gain += 1000;
|
| 135 |
-
|
| 136 |
-
if (gain > best_gain) {
|
| 137 |
-
best_gain = gain;
|
| 138 |
-
candidates.clear();
|
| 139 |
-
candidates.push_back(c);
|
| 140 |
-
} else if (gain == best_gain) {
|
| 141 |
-
candidates.push_back(c);
|
| 142 |
-
}
|
| 143 |
-
} // end while(mask)
|
| 144 |
-
|
| 145 |
-
/* ----- random tie‑break among the best candidates --- */
|
| 146 |
-
uniform_int_distribution<int> dist(0, (int)candidates.size() - 1);
|
| 147 |
-
int chosen = candidates[dist(rng)];
|
| 148 |
-
|
| 149 |
-
/* ----- store the colour -------------------------------- */
|
| 150 |
-
grid[i][j] = chosen;
|
| 151 |
-
used_colours |= (1ULL << chosen);
|
| 152 |
-
|
| 153 |
-
/* ----- mark newly created edges ------------------------ */
|
| 154 |
-
if (i > 0) {
|
| 155 |
-
int nt = grid[i-1][j];
|
| 156 |
-
if (nt != chosen && adj[nt][chosen]) {
|
| 157 |
-
int u = min(nt, chosen), v = max(nt, chosen);
|
| 158 |
-
int eid = edge_id[u][v];
|
| 159 |
-
if (eid != -1 && !covered[eid]) {
|
| 160 |
-
covered[eid] = 1;
|
| 161 |
-
++covered_cnt;
|
| 162 |
-
}
|
| 163 |
-
}
|
| 164 |
-
}
|
| 165 |
-
if (j > 0) {
|
| 166 |
-
int nl = grid[i][j-1];
|
| 167 |
-
if (nl != chosen && adj[nl][chosen]) {
|
| 168 |
-
int u = min(nl, chosen), v = max(nl, chosen);
|
| 169 |
-
int eid = edge_id[u][v];
|
| 170 |
-
if (eid != -1 && !covered[eid]) {
|
| 171 |
-
covered[eid] = 1;
|
| 172 |
-
++covered_cnt;
|
| 173 |
-
}
|
| 174 |
-
}
|
| 175 |
-
}
|
| 176 |
-
} // end for j
|
| 177 |
-
} // end for i
|
| 178 |
-
|
| 179 |
-
if (!ok) continue;
|
| 180 |
-
if (used_colours != all_mask) continue; // not all colours used
|
| 181 |
-
if (covered_cnt != M_edges) continue; // some edges still uncovered
|
| 182 |
-
|
| 183 |
-
/* ----- SUCCESS – convert to 1‑based output ---------------- */
|
| 184 |
-
vector<vector<int>> answer(K, vector<int>(K));
|
| 185 |
-
for (int i = 0; i < K; ++i)
|
| 186 |
-
for (int j = 0; j < K; ++j)
|
| 187 |
-
answer[i][j] = grid[i][j] + 1; // back to 1‑based
|
| 188 |
-
return answer;
|
| 189 |
-
} // end for attempts
|
| 190 |
-
|
| 191 |
-
/* --------------------------------------------------------------
|
| 192 |
-
Very unlikely fallback – deterministic construction
|
| 193 |
-
-------------------------------------------------------------- */
|
| 194 |
-
int Kfallback = max(2 * N, 2);
|
| 195 |
-
Kfallback = min(Kfallback, 240);
|
| 196 |
-
vector<vector<int>> grid(Kfallback, vector<int>(Kfallback, 1));
|
| 197 |
-
int limit = min(N, Kfallback);
|
| 198 |
-
for (int i = 0; i < limit; ++i)
|
| 199 |
-
grid[i][i] = i + 1; // put distinct colours on the diagonal
|
| 200 |
-
|
| 201 |
-
return grid;
|
| 202 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|