#include <iostream> #include <vector> #include <cmath> using namespace std;
const int MAX_N = 100000; const int LOG = 17; int st[MAX_N][LOG]; int log_table[MAX_N + 1];
inline int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; }
void preprocess(const vector<int>& arr, int n) { for (int i = 0; i < n; i++) { st[i][0] = arr[i]; } for (int j = 1; (1 << j) <= n; j++) { for (int i = 0; i + (1 << j) - 1 < n; i++) { st[i][j] = max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]); } } log_table[1] = 0; for (int i = 2; i <= n; i++) { log_table[i] = log_table[i / 2] + 1; } }
int query(int l, int r) { int j = log_table[r - l + 1]; return max(st[l][j], st[r - (1 << j) + 1][j]); }
int main() { int n = read(), m = read(); vector<int> arr(n); for (int i = 0; i < n; i++) { arr[i] = read(); } preprocess(arr, n); while (m--) { int l = read() - 1, r = read() - 1; printf("%d\n", query(l, r)); } return 0; }
#include <iostream> #include <queue> using namespace std;
inline int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; }
int main() { int n = read(); priority_queue<int, vector<int>, greater<int>> pq; for (int i = 0; i < n; i++) { pq.push(read()); } int total_cost = 0; while (pq.size() > 1) { int a = pq.top(); pq.pop(); int b = pq.top(); pq.pop(); int cost = a + b; total_cost += cost; pq.push(cost); } printf("%d\n", total_cost); return 0; }
3.学习总结
本题是典型的贪心算法应用,通过局部最优(每次合并最小的两堆)达到全局最优。
最小堆(优先队列)是一种有效的数据结构,适用于处理动态集合中的最小值问题。
哈夫曼树的构造与本题类似,它用于最优前缀编码问题,具有广泛应用。
由于 n 最大为 10000,使用 O(n log n) 复杂度的方法是合理可行的,若用 O(n^2) 的方法会超时。
#include <iostream> #include <deque> using namespace std;
int main() { int n, m; cin >> n >> m; deque<int> people; for (int i = 1; i <= n; i++) { people.push_back(i); }
while (!people.empty()) { for (int i = 1; i < m; i++) { people.push_back(people.front()); people.pop_front(); } cout << people.front() << " "; people.pop_front(); }
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> using namespace std; int n, m, res[200005]; struct soldier { int id, l, r; } s[400005]; int cmp(soldier a, soldier b) { return a.l < b.l; }
int go[400005][20];
void pre() { for(int i = 1, p = i; i <= 2 * n; i++) { while(p <= 2 * n && s[p].l <= s[i].r) p++; int pos = p - 1; go[i][0] = pos; } for(int i = 1; i < 20; i++) { for(int j = 1; j <= 2 * n; j++) { go[j][i] = go[go[j][i - 1]][i - 1]; } } } void search(int k) { int lmt = s[k].l + m, ans = 1, p = k; for(int i = 19; i >= 0; i--) { if(go[k][i] != 0 && s[go[k][i]].r < lmt) { ans += (1 << i); k = go[k][i]; } } res[s[p].id] = ans + 1; } int main() { cin >> n >> m; for(int i = 1; i <= n; i++) { cin >> s[i].l >> s[i].r; if(s[i].r < s[i].l) s[i].r += m; s[i].id = i; } sort(s + 1, s + 1 + n, cmp); for(int i = 1; i <= n; i++) { s[i + n] = s[i]; s[i + n].l = s[i].l + m; s[i + n].r = s[i].r + m; } pre(); for(int i = 1; i <= n; i++) search(i); for(int i = 1; i <= n; i++) cout << res[i] << " "; return 0; }