Codeforces Round 933 (Div. 3)
A - Rudolf and the Ticket
解題思路:
暴力。
程式碼:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
void solve()
{
int n, m, k;
cin >> n >> m >> k;
vector<int> a(n + 1), b(m + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i <= m; i++)
{
cin >> b[i];
}
int cnt = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (a[i] + b[j] <= k)
{
cnt++;
}
}
}
cout << cnt << endl;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
B - Rudolf and 121
解題思路:
從左到右變成\(0\)即可。
程式碼:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
void solve()
{
int n;
cin >> n;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 2; i <= n - 1; i++)
{
if (a[i - 1] < 0)
{
puts("NO");
return;
}
a[i] -= a[i - 1] * 2;
a[i + 1] -= a[i - 1];
a[i - 1] = 0;
}
for (int i = 1; i <= n; i++)
{
if (a[i] != 0)
{
puts("NO");
return;
}
}
puts("YES");
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C - Rudolf and the Ugly String
解題思路:
\(mapie,map, pie\)都一次能消掉。
程式碼:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
void solve()
{
int n;
cin >> n;
string s;
cin >> s;
s = ' ' + s;
int cnt = 0;
for (int i = 1; i <= n; i++)
{
if (i + 4 <= n)
{
string t = s.substr(i, 5);
if (t == "mapie")
{
cnt++;
i = i + 4;
continue;
}
}
if (i + 2 <= n)
{
string t = s.substr(i, 3);
if (t == "map" || t == "pie")
{
cnt++;
i = i + 2;
}
}
}
cout << cnt << endl;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
D - Rudolf and the Ball Game
解題思路:
\(O(nm)\),直接暴力模擬轉移。
程式碼:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
void solve()
{
int n, m, x;
cin >> n >> m >> x;
vector<bool> dp(n + 1, false);
dp[x] = true;
for (int j = 1; j <= m; j++)
{
vector<bool> cur(n + 1, false);
int d;
char t;
cin >> d >> t;
if (t == '0')
{
for (int i = 1; i <= n; i++)
{
int idx = (i - 1 + d) % n + 1;
cur[idx] = cur[idx] | dp[i];
}
}
else if (t == '1')
{
for (int i = 1; i <= n; i++)
{
int idx = (((i - 1 - d) % n) + n) % n + 1;
cur[idx] = cur[idx] | dp[i];
}
}
else
{
for (int i = 1; i <= n; i++)
{
int idx = (((i - 1 - d) % n) + n) % n + 1;
cur[idx] = cur[idx] | dp[i];
idx = (i - 1 + d) % n + 1;
cur[idx] = cur[idx] | dp[i];
}
}
dp = cur;
}
vector<int> ans;
for (int i = 1; i <= n; i++)
{
if (dp[i])
{
ans.push_back(i);
}
}
cout << ans.size() << endl;
for (auto c : ans)
{
cout << c << ' ';
}
cout << endl;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
E - Rudolf and k Bridges
解題思路:
單調佇列最佳化\(dp\)求取每一列的建橋的最小花費。然後取最小連續段。
程式碼:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
void solve()
{
int n, m, k, d;
cin >> n >> m >> k >> d;
vector<vector<ll>> a(n + 1, vector<ll>(m + 1, 0));
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> a[i][j];
if (j != 1 && j != m)
{
a[i][j]++;
}
}
}
vector<ll> ans(1, 0);
for (int i = 1; i <= n; i++)
{
vector<ll> q(m + 1);
int hh = 0;
int tt = -1;
vector<ll> dp(m + 1);
for (int j = 1; j <= m; j++)
{
while (hh <= tt && j - (q[hh]) > d + 1)
{
hh++;
}
dp[j] = a[i][j];
if (hh <= tt)
{
dp[j] += dp[q[hh]];
}
// cerr << i << ' ' << j << ' ' << dp[j] << endl;
while (hh <= tt && dp[j] < dp[q[tt]])
{
tt--;
}
q[++tt] = j;
}
// cerr << dp[m] << endl;
ans.push_back(dp[m]);
}
for (int i = 1; i <= n; i++)
{
ans[i] += ans[i - 1];
}
ll res = 1e18;
for (int i = 1; i <= n; i++)
{
if (i >= k)
{
res = min(res, ans[i] - ans[i - k] + k * 2);
}
}
cout << res << endl;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
F - Rudolf and Imbalance
解題思路:
找到最大間距和次大間距。
如果最大間距不止一個,答案就是最大間距。
否則想要減小最大間距,就是要往最大間距之間添數字,對於每個\(d\)找能將間距儘量均分,然後和次大間距取較小。
程式碼:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
void solve()
{
int n, m, k;
cin >> n >> m >> k;
vector<ll> a(n + 1), d(m + 1), f(k + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i <= m; i++)
{
cin >> d[i];
}
for (int i = 1; i <= k; i++)
{
cin >> f[i];
}
sort(a.begin() + 1, a.end());
sort(d.begin() + 1, d.end());
sort(f.begin() + 1, f.end());
ll dist = -1;
ll sd = -1;
int cnt = 0;
ll l = 0;
ll r = 0;
for (int i = 2; i <= n; i++)
{
ll t = a[i] - a[i - 1];
if (t > dist)
{
if (dist != -1)
{
sd = dist;
}
dist = t;
cnt = 1;
l = a[i - 1];
r = a[i];
}
else if (t == dist)
{
cnt++;
sd = dist;
}
else
{
if (sd < t)
{
sd = t;
}
}
}
if (cnt > 1)
{
cout << dist << endl;
return;
}
// cerr << l << ' ' << sd << endl;
ll ans = dist;
ll mid = (l + r + 1) / 2;
for (int i = 1; i <= m; i++)
{
ll x = mid - d[i];
auto it = lower_bound(f.begin() + 1, f.end(), x);
if (it != f.end())
{
x = *it;
ll t = d[i] + x;
if (t >= l && t <= r)
{
ans = min(ans, max(r - t, t - l));
if (sd != -1)
{
ans = max(ans, sd);
}
}
}
if (it != f.begin() + 1)
{
it--;
x = *it;
ll t = d[i] + x;
if (t >= l && t <= r)
{
ans = min(ans, max(r - t, t - l));
if (sd != -1)
{
ans = max(ans, sd);
}
}
}
// cerr << i << ' ' << d[i] << ' ' << x << endl;
}
cout << ans << endl;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
G - Rudolf and Subway
解題思路:
根據某些點或者邊的分類特點減虛點。
將原圖轉化到和虛點相連的圖,然後在上面操作。
本題將點與顏色虛點建邊,點到顏色單向邊權值為\(1\),顏色向點建單向邊權值為\(0\)。
跑\(01bfs\)。
程式碼:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
void solve()
{
map<int, int> mp;
int n, m;
cin >> n >> m;
vector<vector<pii>> e(n + m + 1, vector<pii>());
for (int i = 1; i <= m; i++)
{
int a, b, c;
cin >> a >> b >> c;
if (mp.find(c) == mp.end())
{
mp[c] = ++n;
}
c = mp[c];
e[a].push_back({c, 1});
e[c].push_back({a, 0});
e[b].push_back({c, 1});
e[c].push_back({b, 0});
}
deque<int> q;
int st, ed;
cin >> st >> ed;
q.push_front(st);
vector<ll> dist(n + 1, inf);
vector<bool> vis(n + 1, false);
dist[st] = 0;
while (q.size())
{
auto u = q.front();
q.pop_front();
if (vis[u])
{
continue;
}
vis[u] = true;
for (auto t : e[u])
{
auto v = t.fi;
auto w = t.se;
// cerr << u << ' ' << v << endl;
if (dist[v] > dist[u] + w)
{
dist[v] = dist[u] + w;
if (w)
{
q.push_back(v);
}
else
{
q.push_front(v);
}
}
}
}
cout << dist[ed] << endl;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}