Loading

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;
}



比赛链接 https://atcoder.jp/contests/abc373

posted @ 2024-09-28 22:26  _SeiI  阅读(93)  评论(0编辑  收藏  举报