2024.1.28 寒假训练记录(11)

cf一塌糊涂差点爆零,补题!

文章目录

  • CF 1925A We Got Everything Covered!
  • CF 1925B A Balanced Problemset?
  • CF 1925C Did We Get Everything Covered?
  • ATC ABC338D Island Tour
  • ATC ABC338E Chords

CF 1925A We Got Everything Covered!

题目链接

一开始把题目读错了,要求是字母表中的前 k 个字母,重复输出 n 遍即可

#include 

using namespace std;

using i64 = long long;
#define int long long
#define INF 0x3f3f3f3f

typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;

const int N = 11;
const int mod = 998244353;

void solve()
{
	int n, k;
	cin >> n >> k;
	for (int i = 0; i < n; i ++ )
	{
		for (int j = 0; j < k; j ++ )
		{
			cout << (char)('a' + j);
		}
	}
	cout << '\n';
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t = 1;
	cin >> t;
	while (t -- )
	{
		solve();
	}
}

CF 1925B A Balanced Problemset?

题目链接

毒瘤的源泉

因为最后的gcd一定要是x的因子,所以拆出x的所有因子判断 i 和 x / i

#include 

using namespace std;

using i64 = long long;
#define int long long
#define INF 0x3f3f3f3f

typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;

const int N = 11;
const int mod = 998244353;

void solve()
{
	int x, n;
	cin >> x >> n;
	int ans = 1;
	if (n == 1)
	{
		cout << x << '\n';
		return;
	}
	for (int i = 2; i * i <= x; i ++ )
	{
		if (x % i != 0) continue;
		if (i <= x / n) ans = max(ans, i);
		if (x / i * n <= x) ans = max(ans, x / i);
	}
	cout << ans << '\n';
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t = 1;
	cin >> t;
	while (t -- )
	{
		solve();
	}
}

CF 1925C Did We Get Everything Covered?

题目链接

这题昨晚想到了要有 n 个含前 k 个字母的片段,但在实现的时候出现了一点偏差

正确实现方式应该是贪心去找有多少个符合条件的片段,如果少于 n 个的话就输出每个片段的最后一个字母(因为最后一个字母一定是在当前片段中第一次出现的字母)再加上最后不完整片段中没出现的字母

我的错误实现方式:标记在字符串中前 n 次出现的前 k 个字母,判断第 i 次出现的字母后,所有前 k 个字母有没有出现 n - i 次(但是这样可能会出现后方字母顺序混乱的情况)

#include 

using namespace std;

using i64 = long long;
#define int long long
#define INF 0x3f3f3f3f

typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;

const int N = 11;
const int mod = 998244353;

void solve()
{
	int n, k, m;
	cin >> n >> k >> m;
	string s;
	cin >> s;
	set<char> have;
	int cnt = 0;
	vector<char> ans;
	for (int i = 0; i < m; i ++ )
	{
		have.insert(s[i]);
		if (have.size() == k)
		{
			cnt ++ ;
			ans.push_back(s[i]);
			have.clear();
		}
	}
	if (cnt >= n) cout << "Yes\n";
	else
	{
		cout << "No\n";
		int i = 0;
		for (i = 0; i < ans.size(); i ++ ) cout << ans[i];
		if (have.size() == 0)
		{
			for (; i < n; i ++ ) cout << 'a';
		}
		else
		{
			for (int j = 0; j < k; j ++ )
			{
				if (have.find((char)('a' + j)) == have.end())
				{
					for (; i < n; i ++ ) cout << (char)('a' + j);
				}
			}
		}
		cout << '\n';
	}
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t = 1;
	cin >> t;
	while (t -- )
	{
		solve();
	}
}

ATC ABC338D Island Tour

题目链接

昨晚一直在想是二分还是差分,果不其然是差分,但是有一些没见过的trick,积累一下

当一条边都不删去时,最短路径长是固定的,这个可以先计算出来,然后我们再枚举删掉每一条边时对整体路径的影响情况,这可以用差分来降低复杂度,具体看代码吧(需要注意对1 - n 的处理)

以后的最大值都开大大大大大一点!!!!!!!

#include 

using namespace std;

using i64 = long long;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;

const int N = 11;
const int mod = 998244353;

void solve()
{
	int n, m;
	cin >> n >> m;
	vector<int> x(m + 1);
	for (int i = 1; i <= m; i ++ ) cin >> x[i];
	vector<int> suf(n + 2);
	for (int i = 2; i <= m; i ++ )
	{
		if (x[i] > x[i - 1])
		{
			if (x[i] - x[i - 1] < n - (x[i] - x[i - 1]))
			{
				int diff = n - (x[i] - x[i - 1]) - (x[i] - x[i - 1]);
				suf[x[i - 1]] += diff;
				suf[x[i]] -= diff;
			}
			else
			{
				int diff = x[i] - x[i - 1] - (n - (x[i] - x[i - 1]));
				suf[x[i - 1]] -= diff;
				suf[x[i]] += diff;
				suf[n + 1] -= diff;
				suf[1] += diff;
			}			
		}
		else
		{
			if (x[i - 1] - x[i] < n - (x[i - 1] - x[i]))
			{
				int diff = n - (x[i - 1] - x[i]) - (x[i - 1] - x[i]);
				suf[x[i - 1]] -= diff;
				suf[x[i]] += diff;
			}
			else
			{
				int diff = x[i - 1] - x[i] - (n - (x[i - 1] - x[i]));
				suf[x[i - 1]] += diff;
				suf[x[i]] -= diff;
				suf[n + 1] -= diff;
				suf[1] += diff;
			}	
		}
	}

	int ans = 0;
	for (int i = 2; i <= m; i ++ )
	{
		ans += min(abs(x[i] - x[i - 1]), n - abs((x[i] - x[i - 1])));
	}
	int tmp = 0, res = INF;
	for (int i = 1; i <= n; i ++ )
	{
		tmp += suf[i];
		res = min(res, tmp);
	}
	cout << ans + res << '\n';
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t = 1;
	// cin >> t;
	while (t -- )
	{
		solve();
	}
}

ATC ABC338E Chords

题目链接

这题蛮好的说实话,学到了一些新的trick

在环上求弦的交点时可以把环的一条边隔开,拉成一条直线,然后弦就变成了曲线,我们可以通过判断曲线是否有交点来看弦是否有交点

怎么看曲线有没有交点呢,就是关注左右两端点,没有交点的话,左右端点一定是成对出现的,意思是比如说 l1 l2 r1 r2是不合法的一组

所以可以利用栈来判断,左端点就存进去,右端点弹出栈顶,看是不是匹配的左端点,不是就有交点

#include 

using namespace std;

using i64 = long long;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;

const int N = 11;
const int mod = 998244353;

void solve()
{
	int n;
	cin >> n;
	vector<int> a(n), b(n);
	vector<PII> info(2 * n);
	for (int i = 0; i < n; i ++ )
	{
		cin >> a[i] >> b[i];
		if (a[i] > b[i]) swap(a[i], b[i]);
		info[i] = make_pair(a[i], i);
		info[i + n] = make_pair(b[i], i + n);
	}
	sort(info.begin(), info.end());
	stack<int> stk;
	for (int i = 0; i < 2 * n; i ++ )
	{
		if (info[i].second < n) stk.push(info[i].first);
		else
		{
			if (stk.size() == 0)
			{
				cout << "No\n";
				return;
			}
			else
			{
				int t = stk.top();
				stk.pop();
				if (t == a[info[i].second - n]) continue;
				else
				{
					cout << "Yes\n";
					return;
				}
			}
		}
	}
	cout << "No\n";
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t = 1;
	// cin >> t;
	while (t -- )
	{
		solve();
	}
}

你可能感兴趣的:(2024寒假训练记录,算法,c++)