SMU Winter 2025 div1 4th
文章目录
- The Fourth Week
- 一、前言
- 二、算法
- 1.贪心
- <1>(2025暑假训练6 L2-2)
- <2>(2025寒假训练3 C)
- 2.二叉树
- <1>(2025寒假训练6 L2-3)
- 3. 深度优先搜索
- <1>(2025寒假训练6 L2-3)
- 4.排列组合
- <1>(P10912 [蓝桥杯 2024 国 B] 数星星)
- 三、总结
The Fourth Week
人生到处知何似,应似飞鸿踏雪泥。 ————苏轼
一、前言
OI赛制打得很糟糕。
二、算法
1.贪心
<1>(2025暑假训练6 L2-2)
天梯赛的赛场安排 25分、
题解:
给定n个学校的名称和人数,给定每个教室可以容纳的最大人数c。要想到直接把每个学校多余的人排序后放在新开辟的教室即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,c;
const int N = 5010;
int ct[N];
priority_queue<int>a;
map<string,int>mp;
signed main() {
cin >> n >> c;
int ans = 0;
for (int i = 0; i < n; i++) {
string s; int x;
cin >> s >> x;
mp[s] = x/c;
ans += mp[s];
if(x%c) {
a.push(x%c);
cout << s << ' ' << mp[s]+1 << endl;
}else cout << s << ' ' << mp[s] << endl;
}int cnt = 0;
while(!a.empty()) {
int x = a.top(); a.pop();
bool flag = true;
for (int i = 0; i < cnt; i++) {
if(ct[i] + x <= c) {
ct[i] += x;
flag = false;
break;
}
}
if(flag) ct[cnt++] = x;
}cout << cnt+ans << endl;
}
<2>(2025寒假训练3 C)
题解:
平方差。我好像做过?
代码:
#include<iostream>
using namespace std;
int main() {
long long l,r;
long long ans = 0;
cin >> l >> r;
long long rr = 0,ll = 0;
rr += (r+1)/2;
rr += r/4;
l--;
ll += (l+1)/2;
ll += l/4;
cout << rr - ll << endl;
return 0;
}
2.二叉树
<1>(2025寒假训练6 L2-3)
锦标赛 25分
下面还有一种做法
题解:
k轮锦标赛,依次给出每一轮的败者的能力值,最后给出胜者的能力值。输出n个数字表示n名选手的能力值。
代码:
#include <bits/stdc++.h>
using namespace std;
struct node {
int win, lose;
};
bool flag = true;
void solve(node *t, int root, int size) {
if (root * 2 > size || !flag) return;
int gt = t[root * 2 + 1].lose > t[root * 2].lose ? root * 2 + 1 : root * 2;
int le = t[root * 2 + 1].lose > t[root * 2].lose ? root * 2 : root * 2 + 1;
if (t[gt].lose > t[root].win || t[le].lose > t[root].lose) {
flag = false;
} else if (t[gt].lose > t[root].lose) {
t[gt].win = t[root].win;
t[le].win = t[root].lose;
solve(t, root * 2, size);
solve(t, root * 2 + 1, size);
} else {
t[le].win = t[root].win;
t[gt].win = t[root].lose;
solve(t, root * 2, size);
solve(t, root * 2 + 1, size);
if (!flag) {
flag = true;
swap(t[le].win, t[gt].win);
solve(t, root * 2, size);
solve(t, root * 2 + 1, size);
}
}
}
int main() {
int r;
cin >> r;
int l = (2 << (r - 1)) - 1;
node tree[l + 1];
for (int i = r; i > 0; --i) {
int n = 1 << (i - 1);
int s = (2 << (i - 1)) - n;
while (n--) {
cin >> tree[s].lose;
s++;
}
}
cin >> tree[1].win;
if (tree[1].win < tree[1].lose) flag = false;
else solve(tree, 1, l);
if (!flag) cout << "No Solution";
else {
int n = 1 << (r - 1);
int s = (2 << (r - 1)) - n;
while (n--) {
cout << tree[s].win << ' ' << tree[s++].lose;
if (n) cout << ' ';
}
}
return 0;
}
3. 深度优先搜索
<1>(2025寒假训练6 L2-3)
锦标赛 25分
OK啊又是这题,我比较偏向于深度优先搜索的方法,代码简单思维复杂一些
题解:
层层递归,俩者满足一个条件即可,具体看代码。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
int n;
vector<int> a(N);
vector<int> tmp(N),ans(N);
bool dfs(int u,int f){
if(a[f] < a[u]) return false;
if(u > (1 << n - 1)){
int idx = u - (1 << n - 1);
idx += idx - 1;
tmp[idx] = a[u];
tmp[idx + 1] = a[f];
if(u == (1 << n)) ans = tmp;
return true;
}
return (dfs(2 * u - 1,u) && dfs(2 * u,f)) || (dfs(2 * u - 1,f) && dfs(2 * u,u));
}
int main(){
cin >> n;
for(int i = n; i >= 1; --i)
for(int j = (1 << i - 1) + 1; j <= (1 << i); ++j)
cin >> a[j];
cin >> a[1];
if(!dfs(2,1)) cout << "No Solution";
else{
for(int i = 1; i <= (1 << n); ++i) cout << ans[i] << " ";
}
return 0;
}
4.排列组合
<1>(P10912 [蓝桥杯 2024 国 B] 数星星)
思路想到了,排列组合没写对,去精进一下。
题解:
对于l,r之间的每一个询问,查找度大于x的节点,并从中选取x-1个节点组成一颗星星即可,注意x是2的重复情况。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5, mod = 1e9 + 7;
int n, d[N], L, R, ans, cur[N], vis[N];
ll fac[N], infac[N];
ll qpow(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
ll inv(ll a) {
return qpow(a, mod - 2);
}
void init(int n) {
fac[0] = infac[0] = 1;
for (int i = 1; i <= n; i++) {
fac[i] = fac[i - 1] * i % mod;
infac[i] = inv(fac[i]);
}
}
ll C(ll a, ll b){
if (a < b || a < 0 || b < 0) return 0;
return fac[a] * infac[a - b] % mod * infac[b] % mod;
}
ll get(int a) {
if (vis[a] == false) {
vis[a] = true;
for (int i = L - 1; i <= R - 1; i++) {
cur[a] = (cur[a] + C(a, i)) % mod;
}
return cur[a];
}
else return cur[a];
}
int main() {
cin >> n;
for (int i = 1; i <= n - 1; i++) {
int u, v;
cin >> u >> v;
d[u]++, d[v]++;
}
cin >> L >> R;
init(n);
for (int i = 1; i <= n; i++) {
ans = (ans + get(d[i])) % mod;
}
cout << ans << '\n';
return 0;
}
三、总结
整体都打得很糟糕,多方面因素。
OI赛制大多数题目都没有放上去。会做大多数都,但是看不到评测结果所以错的乱七八糟。
最后一周有时间可以再自主训练,多补补题。