2025-7-1
题目出自牛客算法入门班第一章习题:模拟、枚举、贪心:
1013-带权中位数:https://ac.nowcoder.com/acm/contest/20960/1013
1014-双指针:https://ac.nowcoder.com/acm/contest/20960/1014
1015-最短合法子串:https://ac.nowcoder.com/acm/contest/20960/1015
1013-带权中位数
很经典的题,中位数即为答案。
#include <bits/stdc++.h>
#define int long long
#define pii std::pair<int, int>
#define fir first
#define sec second
#define all(x) x.begin(), x.end()
signed main() {
int n;
std::cin >> n;
std::vector<pii> p(n);
for(int i = 0; i < n; i ++ ) {
std::cin >> p[i].fir;
}
int sum = 0;
for(int i = 0; i < n; i ++ ) {
std::cin >> p[i].sec;
sum += p[i].sec;
}
std::sort(all(p));
int pre = 0;
for(int i = 0; i < n; i ++ ) {
pre += p[i].sec;
if(pre >= sum / 2) {
std::cout << i + 1;
break;
}
}
}
1014-双指针
最典型的双指针模板,注意到 \(a_i\) 不可能大于 \(n\) 所以直接用数组计数即可。
#include <bits/stdc++.h>
#define int long long
#define pii std::pair<int, int>
#define fir first
#define sec second
#define all(x) x.begin(), x.end()
signed main() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (auto &x : a) {
std::cin >> x;
}
std::vector<std::pair<int, pii>> ans;
std::vector<int> cnt(n+1, 0);
for(int l = 0, r = 0; r < n; r ++ ) {
cnt[a[r]] ++;
while(l < r && cnt[a[r]] > 1) {
cnt[a[l]] --;
l ++;
}
ans.push_back({r-l+1, {l+1, r+1}});
}
std::sort(all(ans), [&](auto a, auto b) {
if(a.fir == b.fir) return a.sec.fir < b.sec.fir;
return a.fir > b.fir;
});
while(ans.back().fir != ans[0].fir) ans.pop_back();
std::cout << ans.size() << '\n';
for(int i = 0; i < ans.size(); i ++ ) {
std::cout << ans[i].sec.fir << ' ' << ans[i].sec.sec << '\n';
}
}
1015-最短合法子串
双指针枚举所有含有26个不同字母的情况即可。
#include <bits/stdc++.h>
int main() {
std::string str;
std::cin >> str;
std::map<char, int> cnt;
int ans = 1e9;
for(int l = 0, r = 0; r < str.size(); r ++ ) {
cnt[str[r]]++;
while(cnt.size() == 26) {
ans = std::min(ans, r-l+1);
cnt[str[l]]--;
if(cnt[str[l]] == 0) {
cnt.erase(str[l]);
}
l ++;
}
}
if(ans == 1e9) {
std::cout << "-1\n";
}
else {
std::cout << ans << '\n';
}
}