AtCoder Beginner Contest 373
A - September
题意
给\(12\)个字符串,问长度等于标号的字符串个数。
思路
模拟。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int ans = 0;
for (int i = 0; i < 12; i++)
{
string s;
cin >> s;
if (s.size() == i + 1)
{
ans++;
}
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
//cin >> T;
while (T--)
{
solve();
}
return 0;
}
B - 1D Keyboard
题意
给从\(A\)到\(Z\)的\(26\)个英文字母,从\(A\)开始,一次走\(1\)步,每个字母都要走到,问走到\(Z\)要几步。
思路
模拟。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
string s;
cin >> s;
vector<int> v(26);
for (int i = 0; i < s.size(); i++)
{
v[s[i] - 'A'] = i;
}
int ans = 0;
for (int i = 1; i < 26; i++)
{
ans += abs(v[i] - v[i - 1]);
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
//cin >> T;
while (T--)
{
solve();
}
return 0;
}
C - Max Ai+Bj
题意
两个长度为\(n\)的序列,找出\(A_i+B_j\)的最大值。
思路
两个序列各自的最大值之和就是答案。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n, x, maxn1 = LLONG_MIN, maxn2 = LLONG_MIN;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> x;
maxn1 = max(maxn1, x);
}
for (int i = 0; i < n; i++)
{
cin >> x;
maxn2 = max(maxn2, x);
}
cout << maxn1 + maxn2 << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
//cin >> T;
while (T--)
{
solve();
}
return 0;
}
D - Hidden Weights
题意
给\(n\)个点,\(m\)条边及其边权\(w\),给每个点赋权\(x\),使得\(x_{v_j} - x_{u_j} = w_j\),题目保证有解。
思路
从任意一个顶点开始赋值,然后使用\(dfs\)遍历其所有邻点,计算每个顶点的值\(x_{v_j} = x_{u_j} + w_j\)。
代码
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mxn = 1e6 + 5;
int idx;
int to[mxn], nxt[mxn], head[mxn], edge[mxn], ans[mxn];
bool vis[mxn];
void add(int u, int v, int w)
{
to[++idx] = v;
edge[idx] = w;
nxt[idx] = head[u];
head[u] = idx;
}
void dfs(int u, int val)
{
vis[u] = true;
ans[u] = val;
for (int i = head[u]; i; i = nxt[i])
{
int v = to[i];
if (!vis[v])
{
dfs(v, val + edge[i]); // val_v - val_u = edge[i]
}
}
}
void solve()
{
int n, m;
cin >> n >> m;
for (int i = 0; i < m; i++)
{
int u, v, w;
cin >> u >> v >> w;
u--, v--;
add(u, v, w);
add(v, u, -w); // 反向边
}
for (int i = 0; i < n; i++) // 遍历所有点,防止不连通
{
if (!vis[i])
{
dfs(i, 0);
}
}
for (int i = 0; i < n; i++)
{
cout << ans[i] << " ";
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
while (T--)
{
solve();
}
return 0;
}
E - How to Win the Election
题意
\(n\)个人竞选,有 \(k\)张选票,已知第\(i\)个人已经有\(a_i\)张票。当票比自己多的人\(< m\)时能选上。对于第\(i\)个人,一定选上输出\(0\),一定选不上输出\(-1\),其他输出选上需要的最少额外票数。
思路
如果\(n=m\),所有人都能选上;否则,对每个人都二分一次进前\(m\)个所需票数,再二分一次判断把剩下的票都给别人是否能进前\(m\)个(即被选上)。
代码
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, m, k;
vector<int> org, a, sum;
bool check(int idx, int mid)
{
// 第二层二分多少人可以超过当前竞选者
int cnt = 0, cur = org[idx] + mid, rest = k - mid;
int p = upper_bound(a.begin() + 1, a.end(), cur) - (a.begin() + 1);
if (org[idx] < a[n - m + 1]) // idx不在前m大的人当中
{
if (p < n - m + 1)
{
return false;
}
return (p - n + m) * (cur + 1) - (sum[p] - sum[n - m]) > rest; // 让前边每个人的票都比cur多1,看剩下的票够不够
}
// 往外扩一个
return (p - n + m) * (cur + 1) - (sum[p] - sum[n - m - 1]) + org[idx] > rest; // sum里面多减了所以org[idx]要加回来
}
void solve()
{
cin >> n >> m >> k;
if (n == m)
{
for (int i = 0; i < n; i++)
{
cout << "0 ";
}
return;
}
org.resize(n + 1);
a.resize(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> org[i];
k -= org[i]; // k是剩下的票
}
a = org;
sort(a.begin() + 1, a.end());
sum.resize(n + 1);
vector<int> ans(n + 1);
for (int i = 1; i <= n; i++)
{
sum[i] = sum[i - 1] + a[i];
}
for (int i = 1; i <= n; i++)
{
int l = 0, r = k, res = -1;
while (l <= r) // 第一层二分需要的票数
{
int mid = (l + r) >> 1;
if (check(i, mid))
{
res = mid;
r = mid - 1;
}
else
{
l = mid + 1;
}
}
ans[i] = res;
}
for (int i = 1; i <= n; i++)
{
cout << ans[i] << " ";
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
//cin >> T;
while (T--)
{
solve();
}
return 0;
}