日常刷题2025-1-23

日常刷题2025-1-23

rating:1400

https://codeforces.com/problemset/problem/1955/D

思路(定长滑动窗口)

定长滑动窗口,r 只管加, l 只管减即可。

代码

#include <bits/stdc++.h>
typedef std::pair<long long, long long> pll;
typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 1e5+5;
void solve(){
int n, m, k;
std::cin >> n >> m >> k;
std::map<int, int> dic;
std::vector<int> a(n), b(m);
for (int i = 0; i < n; i++){
std::cin >> a[i];
}
for (int i = 0; i < m; i++){
std::cin >> b[i];
dic[b[i]] += 1;
}
std::map<int, int> mp;
int l = 0, r = 0, cnt = 0, ans = 0;
while (r < n){
if (dic[a[r]] != 0) {
mp[a[r]] += 1;
if (mp[a[r]] <= dic[a[r]]) cnt++;
}
if (r - l + 1 < m) {
r++;
continue;
}
ans += cnt >= k;
if (dic[a[l]] != 0){
mp[a[l]] -= 1;
if (mp[a[l]] < dic[a[l]]) cnt--;
}
l++;
r++;
}
std::cout << ans << '\n';
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);
int t = 1, i;
std::cin >> t;
for (i = 0; i < t; i++){
solve();
}
return 0;
}

C. Ticket Hoarding

rating:1400

https://codeforces.com/problemset/problem/1951/C

思路(贪心)

看着像DP,但是一看 k 的取值范围,DP放弃,只能想一想贪心。如果有一个购买序列b,b任意排序不会影响最终的增量add,因为增加的值是确定的。所以我们可以排序,每次贪心的买价格最少的就行。

代码

#include <bits/stdc++.h>
typedef std::pair<long long, long long> pll;
typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 1e5+5;
void solve(){
int n, m, k;
std::cin >> n >> m >> k;
std::vector<int> a(n+1);
for (int i = 1; i <= n; i++){
std::cin >> a[i];
}
std::sort(a.begin() + 1, a.end());
i64 ans = 0, add = 0;
for (int i = 1; i <= n; i++){
ans += std::min(m, k) * (a[i] + add);
add += std::min(m, k);
k -= std::min(m, k);
}
std::cout << ans << '\n';
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);
int t = 1, i;
std::cin >> t;
for (i = 0; i < t; i++){
solve();
}
return 0;
}

E. Nearly Shortest Repeating Substring

rating:1500

https://codeforces.com/problemset/problem/1950/E

思路(枚举因子+小巧思)

我们先思考一下知道循环长度时答案可能是什么,假设循环长度为 x,答案序列为 k ,则答案一定是 s 字符串开头 x 个或者 s 字符串最后 x 个之一。为什么?

如果开头 x 个不可行,那么说明开头 x 个字符中至少有一个字符与 k 不同,如果最后 x 个也不行,也说明同样的结果,那么如果选开头和选结尾都不行的话,选其他任何的x个字符也一定不行,因为开头和结尾已经各有一个和答案序列不同了。所以 x 这个长度的循环行不行取决为开头和结尾 x 个字符。

那么如何得到 x 呢?

很显然 x 一定只能是 n 的因子,所以我们只需要 log n 的复杂度枚举每一个可行的 x 然后计算是否可行即可。O(nlogn)

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 5;
vector<int> e[maxn];
int n;
string s, t;
bool check(int x) {
int cnts = 0, cntt = 0;
for (int i = x; i < n; i++) {
if (s[i % x] != s[i]) cnts++;
if (t[i % x] != t[i]) cntt++;
}
if (cnts <= 1 || cntt <= 1) return true;
return false;
}
void solve() {
cin >> n >> s;
t = s;
reverse(t.begin(), t.end());
vector<int> v;
for (int i = 1; i * i <= n; i++) {
if (n % i != 0) continue ;
v.push_back(n / i);
v.push_back(i);
}
sort(v.begin(), v.end());
for (int i = 0; i < v.size(); i++) {
if (check(v[i])) {
cout << v[i] << endl;
return ;
}
}
}
int main() {
int T = 1;
cin >> T;
while (T--) solve();
}

本文作者:califeee

本文链接:https://www.cnblogs.com/califeee/p/18687116

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   califeee  阅读(2)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.