mirror of
https://github.com/InternLM/InternBootcamp.git
synced 2026-04-28 17:29:37 +00:00
init-commit
This commit is contained in:
commit
18a552597a
3461 changed files with 1150579 additions and 0 deletions
276
internbootcamp/bootcamp/cdrazillikesheap/cdrazillikesheap.py
Executable file
276
internbootcamp/bootcamp/cdrazillikesheap/cdrazillikesheap.py
Executable file
|
|
@ -0,0 +1,276 @@
|
|||
"""#
|
||||
|
||||
### 谜题描述
|
||||
Drazil likes heap very much. So he created a problem with heap:
|
||||
|
||||
There is a max heap with a height h implemented on the array. The details of this heap are the following:
|
||||
|
||||
This heap contains exactly 2^h - 1 distinct positive non-zero integers. All integers are distinct. These numbers are stored in the array a indexed from 1 to 2^h-1. For any 1 < i < 2^h, a[i] < a[\left ⌊{i/2}\right ⌋].
|
||||
|
||||
Now we want to reduce the height of this heap such that the height becomes g with exactly 2^g-1 numbers in heap. To reduce the height, we should perform the following action 2^h-2^g times:
|
||||
|
||||
Choose an index i, which contains an element and call the following function f in index i:
|
||||
|
||||
<image>
|
||||
|
||||
Note that we suppose that if a[i]=0, then index i don't contain an element.
|
||||
|
||||
After all operations, the remaining 2^g-1 element must be located in indices from 1 to 2^g-1. Now Drazil wonders what's the minimum possible sum of the remaining 2^g-1 elements. Please find this sum and find a sequence of the function calls to achieve this value.
|
||||
|
||||
Input
|
||||
|
||||
The first line of the input contains an integer t (1 ≤ t ≤ 70 000): the number of test cases.
|
||||
|
||||
Each test case contain two lines. The first line contains two integers h and g (1 ≤ g < h ≤ 20). The second line contains n = 2^h-1 distinct positive integers a[1], a[2], …, a[n] (1 ≤ a[i] < 2^{20}). For all i from 2 to 2^h - 1, a[i] < a[\left ⌊{i/2}\right ⌋].
|
||||
|
||||
The total sum of n is less than 2^{20}.
|
||||
|
||||
Output
|
||||
|
||||
For each test case, print two lines.
|
||||
|
||||
The first line should contain one integer denoting the minimum sum after reducing the height of heap to g. The second line should contain 2^h - 2^g integers v_1, v_2, …, v_{2^h-2^g}. In i-th operation f(v_i) should be called.
|
||||
|
||||
Example
|
||||
|
||||
Input
|
||||
|
||||
|
||||
2
|
||||
3 2
|
||||
7 6 3 5 4 2 1
|
||||
3 2
|
||||
7 6 5 4 3 2 1
|
||||
|
||||
|
||||
Output
|
||||
|
||||
|
||||
10
|
||||
3 2 3 1
|
||||
8
|
||||
2 1 3 1
|
||||
|
||||
Here is a reference code to solve this task. You can use this to help you genereate cases or validate the solution.
|
||||
```python
|
||||
#include <bits/stdc++.h>
|
||||
#pragma GCC optimize(\"O3\")
|
||||
#pragma GCC optimize(\"unroll-loops\")
|
||||
#pragma comment(linker, \"/STACK:2000000\")
|
||||
using namespace std;
|
||||
using ll = long long;
|
||||
using db = long double;
|
||||
using ii = pair<int, int>;
|
||||
const int N = 3e5 + 5, LG = 19, MOD = 998244353;
|
||||
const int SQ = 320;
|
||||
const long double EPS = 1e-7;
|
||||
int d, m, t;
|
||||
bool deletable[1 << 22];
|
||||
int h, g, a[1 << 22];
|
||||
int pos[1 << 22];
|
||||
void dfs(int node, int height) {
|
||||
if (height > g) return;
|
||||
deletable[node] = false;
|
||||
dfs(node << 1, height + 1);
|
||||
dfs(node << 1 | 1, height + 1);
|
||||
}
|
||||
int get(int x) {
|
||||
if (a[x << 1] == 0 && a[x << 1 | 1] == 0)
|
||||
return x;
|
||||
else {
|
||||
if (a[x << 1] > a[x << 1 | 1])
|
||||
return get(x << 1);
|
||||
else
|
||||
return get(x << 1 | 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
void apply(int x) {
|
||||
if (a[x << 1] == 0 && a[x << 1 | 1] == 0) {
|
||||
a[x] = 0;
|
||||
} else {
|
||||
a[x] = max(a[x << 1], a[x << 1 | 1]);
|
||||
pos[a[x]] = x;
|
||||
if (a[x << 1] > a[x << 1 | 1])
|
||||
return apply(x << 1);
|
||||
else
|
||||
return apply(x << 1 | 1);
|
||||
}
|
||||
}
|
||||
vector<int> vt;
|
||||
int ptr;
|
||||
vector<int> ans;
|
||||
bool kill() {
|
||||
assert(ptr < vt.size());
|
||||
int x = vt[ptr++];
|
||||
int y = get(pos[x]);
|
||||
if (y == -1) {
|
||||
cout << -1 << '\n';
|
||||
exit(0);
|
||||
}
|
||||
if (deletable[y]) {
|
||||
ans.push_back(pos[x]);
|
||||
apply(pos[x]);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
int32_t main() {
|
||||
ios_base::sync_with_stdio(0);
|
||||
cin.tie(0);
|
||||
cin >> t;
|
||||
while (t--) {
|
||||
cin >> h >> g;
|
||||
for (int i = 1; i < 1 << h; i++) {
|
||||
cin >> a[i];
|
||||
a[i + i] = a[i + i + 1] = 0;
|
||||
pos[a[i]] = i;
|
||||
vt.push_back(a[i]);
|
||||
}
|
||||
sort(vt.rbegin(), vt.rend());
|
||||
fill(deletable, deletable + (1 << h), 1);
|
||||
dfs(1, 1);
|
||||
int cur = (1 << h);
|
||||
while (cur != (1 << g)) {
|
||||
cur -= kill();
|
||||
}
|
||||
cout << accumulate(a, a + (1 << h), 0ll) << '\n';
|
||||
for (auto x : ans) cout << x << ' ';
|
||||
cout << '\n';
|
||||
ans.clear();
|
||||
vt.clear();
|
||||
ptr = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
请完成上述谜题的训练场环境类实现,包括所有必要的方法。
|
||||
"""
|
||||
|
||||
from bootcamp import Basebootcamp
|
||||
import random
|
||||
import heapq
|
||||
import re
|
||||
from itertools import count
|
||||
from bootcamp import Basebootcamp
|
||||
|
||||
class Cdrazillikesheapbootcamp(Basebootcamp):
|
||||
def __init__(self, h_range=(3, 5)):
|
||||
self.min_h, self.max_h = h_range # 控制合理的堆高度范围
|
||||
|
||||
def case_generator(self):
|
||||
h = random.randint(self.min_h, self.max_h)
|
||||
g = random.randint(max(1, h-2), h-1) # 保证足够的操作次数
|
||||
n = (1 << h) - 1
|
||||
|
||||
# 生成满足最大堆条件的数组
|
||||
values = random.sample(range(1, (1 << 20)), n)
|
||||
heapq._heapify_max(values)
|
||||
|
||||
# 构建完全二叉树结构
|
||||
heap = [0]*n
|
||||
for i in range(n):
|
||||
heap[i] = values[i]
|
||||
if i > 0:
|
||||
parent = (i-1) // 2
|
||||
assert heap[parent] > heap[i], "Invalid heap structure"
|
||||
|
||||
return {
|
||||
'h': h,
|
||||
'g': g,
|
||||
'array': heap
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def prompt_func(case) -> str:
|
||||
prompt = (
|
||||
f"## 堆高度缩减问题\n"
|
||||
f"初始堆高度为{case['h']},需要缩减至高度{case['g']}\n"
|
||||
f"堆数组:{' '.join(map(str, case['array']))}\n\n"
|
||||
"**操作规则**:\n"
|
||||
"1. 每次操作选择节点i调用f(i)\n"
|
||||
"2. f(i)将节点值替换为较大子节点的值,递归处理直到叶子节点置零\n"
|
||||
"3. 最终保留的节点必须构成高度{case['g']}的有效最大堆\n\n"
|
||||
"**答案格式**:\n"
|
||||
"[answer]\n"
|
||||
"总和值\n"
|
||||
"操作序列(空格分隔)\n"
|
||||
"[/answer]"
|
||||
)
|
||||
return prompt
|
||||
|
||||
@staticmethod
|
||||
def extract_output(text):
|
||||
pattern = r'\[answer\](.*?)\[/answer\]'
|
||||
matches = re.findall(pattern, text, re.DOTALL)
|
||||
if not matches:
|
||||
return None
|
||||
|
||||
last_match = matches[-1].strip()
|
||||
try:
|
||||
sum_line, ops_line = last_match.split('\n')[:2]
|
||||
return {
|
||||
'sum': int(sum_line.strip()),
|
||||
'operations': list(map(int, ops_line.strip().split()))
|
||||
}
|
||||
except:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def _verify_correction(cls, solution, case):
|
||||
if not solution or 'sum' not in solution or 'operations' not in solution:
|
||||
return False
|
||||
|
||||
h, g = case['h'], case['g']
|
||||
expected_ops = (1 << h) - (1 << g)
|
||||
if len(solution['operations']) != expected_ops:
|
||||
return False
|
||||
|
||||
# 构建堆结构
|
||||
size = (1 << h)
|
||||
a = [0] * size
|
||||
for i, val in enumerate(case['array'], 1):
|
||||
a[i] = val
|
||||
|
||||
# 模拟操作
|
||||
for op in solution['operations']:
|
||||
if op >= size or a[op] == 0:
|
||||
return False
|
||||
|
||||
current = op
|
||||
while True:
|
||||
left = 2 * current
|
||||
right = 2 * current + 1
|
||||
|
||||
# 边界检查
|
||||
if left >= size:
|
||||
a[current] = 0
|
||||
break
|
||||
|
||||
# 查找最大子节点
|
||||
max_child = left if a[left] > a[right] else right
|
||||
if a[max_child] == 0:
|
||||
a[current] = 0
|
||||
break
|
||||
|
||||
# 替换节点值
|
||||
a[current] = a[max_child]
|
||||
current = max_child
|
||||
|
||||
# 验证最终堆结构
|
||||
valid_size = (1 << g) - 1
|
||||
for i in range(1, valid_size+1):
|
||||
if a[i] == 0:
|
||||
return False
|
||||
|
||||
for i in range(1, valid_size+1):
|
||||
left = 2*i
|
||||
right = 2*i+1
|
||||
if left <= valid_size and a[i] < a[left]:
|
||||
return False
|
||||
if right <= valid_size and a[i] < a[right]:
|
||||
return False
|
||||
|
||||
return sum(a[1:valid_size+1]) == solution['sum']
|
||||
Loading…
Add table
Add a link
Reference in a new issue