目录
3.C. Rudolf and the Ugly String
1.A. Rudolf and the Ticket
暴力签到题,两次for循环搞定。
#include<iostream>
#include<set>
#include<map>
#include<string>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdlib.h>
#define ll long long
using namespace std;
const int N = 200010;
const int M = 500010;
const int inf = 1234567890;
ll a[N], b[N], c[N];
void solve()
{
ll n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= m; i++ ) cin >> b[i];
ll ans = 0;
sort(a + 1, a + 1 + n);
sort(b + 1, b + 1 + m);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++)
{
if (a[i] + b[j] <= k) ans++;
else break;
}
}
cout << ans << "\n";
}
int main()
{
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
2.B. Rudolf and 121
题意:题目给出一个数组,要求我们将这个数组的元素全部变成0,只能进行一种操作多次或者不操作。
选择一个索引r,1<r<n(数组长度),对索引位置的元素-2,旁边两元素都-1。
思路:我们发现最左边的元素的大小改变与它右边的元素有关,那我们直接遍历一遍,如果此时的元素不为0,那个它右边的元素就减去2*这个元素,它右边的右边的元素减去相同值,如果出现负数,则证明这个数组不能通过这个操作全部变成0。
AC代码:
#include<iostream>
#include<set>
#include<map>
#include<string>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdlib.h>
#define ll long long
using namespace std;
const int N = 200010;
const int M = 500010;
const int inf = 1234567890;
ll a[N], b[N], c[N];
void solve()
{
ll n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
if (n == 3)
{
if (a[1] != a[3])
{
cout << "NO\n";
}
else
{
if (a[2] - 2 * a[1] != 0)
{
cout << "NO\n";
}
else cout << "YES\n";
}
return;
}
for (int i = 2; i <= n-1; i++)
{
if (a[i - 1] == 0)
continue;
else
{
a[i] -= 2 * a[i - 1];
a[i + 1] -= a[i - 1];
a[i - 1] = 0;
if (a[i] < 0) break;
if (a[i + 1] < 0) break;
}
}
for (int i = 1; i <= n; i++)
{
if (a[i] != 0)
{
cout << "NO\n";
return;
}
}
cout << "YES\n";
}
int main()
{
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
3.C. Rudolf and the Ugly String
思路:其实就是找"map"和"pie"的个数,但是会有"mapie"的出现,这时只需删除一个即可。
AC代码:
#include<iostream>
#include<set>
#include<map>
#include<string>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdlib.h>
#define ll long long
using namespace std;
const int N = 200010;
const int M = 500010;
const int inf = 1234567890;
ll a[N], b[N], c[N];
void solve()
{
int n;
cin >> n;
string s;
cin >> s;
int cnt1 = 0, cnt2 = 0;
vector<int>q;
for (int i = 0; i < n-2; i++)
{
if (s[i] == 'm' && s[i + 1] == 'a' && s[i + 2] == 'p') cnt1++,q.push_back(i+2);
if (s[i] == 'p' && s[i + 1] == 'i' && s[i + 2] == 'e') cnt2++,q.push_back(i);
}
sort(q.begin(), q.end());
ll ans = cnt1 + cnt2;
for (int i = 1; i < q.size(); i++)
if (q[i] == q[i - 1])ans--;
cout << ans << "\n";
}
int main()
{
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
4.D. Rudolf and the Ball Game
其实就是按照规律顺时针逆时针转,?保留两个进去,我在当时是使用了bfs去解决,但是内存直接暴了,看来题解才发现自己多愚蠢。
下面是AC代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
#include <cmath>
#include <set>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 1e5 + 10, M = N * 2, mod = 1e9 + 7;
int T, n, m, a;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> T;
while (T--)
{
cin >> n >> m >> a;
set<int> q[2]; // q[0]所有元素扩展出来的放入q[1],然后清空q[0]
int ix = 0; // q[1]所有元素扩展出来的放入q[0],然后清空q[1]
q[ix].insert(a);
while (m--)
{
int x;
char ch;
cin >> x >> ch;
while (q[ix].size())
{
int u = *(q[ix].begin()); // 一边遍历一边删除,非常有用的技巧,使用for循环一遍遍历set一遍删除是不可以的,但是这里这种方式是可以的
q[ix].erase(u);
if (ch == '0' || ch == '?') // 顺时针
{
q[ix ^ 1].insert((u + x - 1) % n + 1);
}
if (ch == '1' || ch == '?') // 逆时针
{
q[ix ^ 1].insert((u - x - 1 + n) % n + 1);
}
}
ix ^= 1; // 采取异或操作,只需要使用一个大小为2的set维护即可,相比直接使用2个set,这种写法非常巧妙,可以减少代码量
}
cout << q[ix].size() << '\n'; // 此时的q[ix]就是最终可以扩展出来的所有位置
for (auto &t : q[ix])
{
cout << t << ' ';
}
cout << '\n';
}
return 0;
}