2024.2.3 寒假训练记录(17)

补一下牛客,菜得发昏了,F搞了两个小时都没搞出来,不如去开H了

在这里插入图片描述
还没补完 剩下的打了atc再来

文章目录

  • 牛客 寒假集训1A DFS搜索
  • 牛客 寒假集训1B 关鸡
  • 牛客 寒假集训1C 按闹分配
  • 牛客 寒假集训1D 数组成鸡
  • 牛客 寒假集训1E 本题又主要考察了贪心
  • 牛客 寒假集训1G why买外卖
  • 牛客 寒假集训1H 01背包,但是bit

牛客 寒假集训1A DFS搜索

题目链接

看数据很小于是纯暴力解法

#include 

using namespace std;

#define int long long
using i64 = long long;

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

const int N = 1000010;

void solve()
{
	int n;
	cin >> n;
	string s;
	cin >> s;
	bool flag1 = false, flag2 = false;
	for (int i = 0; i < n; i ++ )
	{
		if (s[i] == 'd')
		{
			for (int j = i + 1; j < n; j ++ )
			{
				if (s[j] == 'f')
				{
					for (int k = j + 1; k < n; k ++ )
					{
						if (s[k] == 's')
						{
							flag1 = true;
							break;
						}
					}
					if (flag1) break;
				}
			}
			if (flag1) break;
		}
	}
	for (int i = 0; i < n; i ++ )
	{
		if (s[i] == 'D')
		{
			for (int j = i + 1; j < n; j ++ )
			{
				if (s[j] == 'F')
				{
					for (int k = j + 1; k < n; k ++ )
					{
						if (s[k] == 'S')
						{
							flag2 = true;
							break;
						}
					}
					if (flag2) break;
				}
			}
			if (flag2) break;
		}
	}
	if (flag2) cout << 1 << ' ';
	else cout << 0 << ' ';
	if (flag1) cout << 1 << '\n';
	else cout << 0 << '\n';
}

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

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

牛客 寒假集训1B 关鸡

题目链接

我是分两种讨论,从左边出去和从右边出去,先把坐标按y从小到大排序,遍历每一个坐标,看下一个坐标是不是在当前坐标的下面或者右下面或者右上面,是的话当前这一端就封死了

答案最大是3(在鸡的左右下)

#include 

using namespace std;

#define int long long
using i64 = long long;

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

const int N = 1000010;

bool cmp(PII a, PII b)
{
	if (a.second != b.second) return a.second < b.second;
	else return a.first < b.first;
}

void solve()
{
	int n;
	cin >> n;
	vector<PII> pos(n);
	int cnt = 0;
	for (int i = 0; i < n; i ++ )
	{
		cin >> pos[i].first >> pos[i].second;
		if (pos[i].first == 1 && pos[i].second == -1) cnt ++ ;
		if (pos[i].first == 1 && pos[i].second == 1) cnt ++ ;
		if (pos[i].first == 2 && pos[i].second == 0) cnt ++ ;
	}
	sort(pos.begin(), pos.end(), cmp);
	if (n == 0)
	{
		cout << 3 << '\n';
		return;
	}
	if (cnt == 3)
	{
		cout << 0 << '\n';
		return;
	}
	bool flag1 = false, flag2 = false;
	for (int i = 0; i < n - 1; i ++ )
	{
		int x = pos[i].first, y = pos[i].second;
		if (y < 0)
		{
			if (flag1) continue;
			if (x == 1)
			{
				if (pos[i + 1].first == 2 && (pos[i + 1].second == y || pos[i + 1].second == y + 1)) flag1 = true;
			}
			else
			{
				if (pos[i + 1].first == 1 && pos[i + 1].second == y + 1) flag1 = true;
			}
		}
		else
		{
			if (flag2) break;
			if (x == 1)
			{
				if (pos[i + 1].first == 2 && (pos[i + 1].second == y || pos[i + 1].second == y + 1)) flag2 = true;
			}
			else
			{
				if (pos[i + 1].first == 1 && pos[i + 1].second == y + 1) flag2 = true;
			}
		}
	}
	if (flag1 && flag2) cout << 0 << '\n';
	else if (flag1)
	{
		int x = pos[n - 1].first, y = pos[n - 1].second;
		if (y >= 0) cout << 1 << '\n';
		else cout << 2 << '\n';
	}
	else if (flag2)
	{
		int x = pos[0].first, y = pos[0].second;
		if (y <= 0) cout << 1 << '\n';
		else cout << 2 << '\n';
	}
	else
	{
		int ans = 0;
		int x1 = pos[0].first, y1 = pos[0].second;
		int x2 = pos[n - 1].first, y2 = pos[n - 1].second;
		if (y1 <= 0) ans ++ ;
		else ans += 2;
		if (y2 >= 0) ans ++ ;
		else ans += 2;
		ans = min((i64)3, min(ans, 3 - cnt));
		cout << ans << '\n';
	}
}

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

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

牛客 寒假集训1C 按闹分配

题目链接

不知道为啥赛时脑抽写二分,实际上 O ( n ) O(n) O(n) 处理一下前缀和就搞定了

鸡插到某一个人前面,那增加的不满意度就是 t c t_c tc 乘上在鸡后面的人数,根据这个就能算出鸡最优能站在第几个人前面,剩下的前缀和就搞定了

下面代码还是二分,懒得写qaq

#include 

using namespace std;

#define int long long
using i64 = long long;

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

const int N = 1000010;

void solve()
{
	int n, q, c;
	cin >> n >> q >> c;
	vector<int> t(n + 1), pre(n + 1), tmp(n + 2);
	for (int i = 1; i <= n; i ++ ) cin >> t[i], pre[i] = pre[i - 1] + t[i];
	for (int i = 1; i <= n; i ++ ) pre[i] = pre[i - 1] + pre[i];
	sort(t.begin(), t.end());
	for (int i = 1; i <= n + 1; i ++ ) tmp[i] = tmp[i - 1] + t[i - 1];
	while (q -- )
	{
		int m;
		cin >> m;
		auto check = [&](int mid)
		{
			int pos = upper_bound(tmp.begin(), tmp.end(), mid) - tmp.begin() - 1;
			int time = pre[n] + (n - pos + 1) * c;
			if (time - pre[n] > m) return false;
			else return true;
		};
		int l = 0, r = pre[n];
		while (l < r)
		{
			int mid = l + r >> 1;
			if (check(mid)) r = mid;
			else l = mid + 1;
		}
		cout << r + c << '\n';
	}
}

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

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

牛客 寒假集训1D 数组成鸡

题目链接

这题又可以学到一个trick,m的范围在1e9之内,但是30个2相乘就已经超过了,所以n给那么大完全是吓唬人的,如果n很大,那只能说明有很多一样的数要变成1 or -1,所以枚举每一个数变成-1开始到更小,从1开始到更大,只要乘积超过1e9直接停就可以了,最后要注意,如果一个数是0,乘积就肯定是0,所以0是很容易达成的,直接在一开始把0加入到可以得到的集合中,之后询问时每次查找集合中有没有这个数就可以了

#include 

using namespace std;

#define int long long
using i64 = long long;

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

const int N = 1000010;
const int maxn = 1e6;
const int mod = 1e9 + 7;

void solve()
{
	int n, q;
	cin >> n >> q;
	vector<int> a(n);
	for (int i = 0; i < n; i ++ ) cin >> a[i];
	sort(a.begin(), a.end());
	set<int> st;
	st.insert(0);
	auto check = [&](int x)
	{
		int res = 1;
		for (int i = 0; i < n; i ++ )
		{
			res *= a[i] + x;
			if (res > 1e9) return false;
		}
		st.insert(res);
		return true;
	};
	for (int i = 0; i < n; i ++ )
	{
		if (i != n - 1 && a[i] == a[i - 1]) continue;
		for (int j = -a[i] - 1; check(j); j -- ) ;
		for (int j = -a[i] + 1; check(j); j ++ ) ;
	}
	while (q -- )
	{
		int m;
		cin >> m;
		cout << (st.count(m) ? "Yes" : "No") << '\n';
	}
}

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

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

牛客 寒假集训1E 本题又主要考察了贪心

题目链接

数据范围很小,dfs就可以

#include 

using namespace std;

#define int long long
using i64 = long long;

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

const int N = 1000010;

void solve()
{
	int n, m;
	cin >> n >> m;
	vector<int> a(n + 1);
	for (int i = 1; i <= n; i ++ ) cin >> a[i];
	vector<PII> op;
	for (int i = 0; i < m; i ++ )
	{
		int x, y;
		cin >> x >> y;
		if (x == 1 || y == 1) a[1] += 3;
		else op.push_back(make_pair(x, y));
	}

	int ans = n;
	m = op.size();
	function<void(int)> dfs = [&](int u)
	{
		if (u == m)
		{
			int cnt = 0;
			for (int i = 2; i <= n; i ++ )
			{
				if (a[i] > a[1]) cnt ++ ;
			}
			ans = min(cnt + 1, ans);
			return;
		}
		int id1 = op[u].first, id2 = op[u].second;
		a[id1] ++ , a[id2] ++ ;
		dfs(u + 1);
		a[id1] += 2, a[id2] -- ;
		dfs(u + 1);
		a[id1] -= 3, a[id2] += 3;
		dfs(u + 1);
		a[id2] -= 3;
	};

	dfs(0);
	cout << ans << '\n';
}

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

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

牛客 寒假集训1G why买外卖

题目链接

优惠券按照a排序,遍历一遍即可,利用前缀和

#include 

using namespace std;

#define int long long
using i64 = long long;

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

const int N = 1000010;

bool cmp(PII a, PII b)
{
	if (a.first != b.first) return a.first < b.first;
	else return a.second > b.second;
}

void solve()
{
	int n, m;
	cin >> n >> m;
	vector<PII> info(n);
	for (int i = 0; i < n; i ++ ) cin >> info[i].first >> info[i].second;
	sort(info.begin(), info.end(), cmp);
	int pre = 0;
	int i = 0, ans = m;
	for (i = 0; i < n; i ++ )
	{
		pre += info[i].second;
		if (info[i].first - pre > m) continue;
		else
		{
			int used = info[i].first - pre;
			ans = max(ans, info[i].first + m - used);
		}
	}
	cout << ans << '\n';
}

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

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

牛客 寒假集训1H 01背包,但是bit

题目链接

按照题解思路写的,枚举m的二进制中的每一位1,让最后的总重量在该位为0,在这一位之后的可以随便取,在这一位之前的必须是m的子集(意思是m那一位不为1的,总重量的那一位也不能为1),取最大值即可

#include 

using namespace std;

#define int long long
using i64 = long long;

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

const int N = 1000010;
const int maxn = 1e5 + 1;
const int mod = 1e9 + 7;

void solve()
{
	int n, m;
	cin >> n >> m;
	vector<int> v(n), w(n);
	for (int i = 0; i < n; i ++ ) cin >> v[i] >> w[i];
	int ans = 0;
	for (int j = 0; j < n; j ++ )
	{
		bool flag = true;
		for (int k = 0; k <= 30; k ++ )
		{
			if ((((w[j] >> k) & 1) == 1) && (((m >> k) & 1) == 0))
			{
				flag = false;
				break;
			}
		}
		if (flag) ans += v[j];
	}
	for (int i = 0; i <= 30; i ++ )
	{
		if ((m & (1 << i)) == 0) continue;
		int tmp = 0;
		for (int j = 0; j < n; j ++ )
		{
			bool flag = true;
			if (((w[j] >> i) & 1) == 1) continue;
			for (int k = i + 1; k <= 30; k ++ )
			{
				if ((((w[j] >> k) & 1) == 1) && (((m >> k) & 1) == 0))
				{
					flag = false;
					break;
				}
			}
			if (flag) tmp += v[j];
		}
		ans = max(ans, tmp);
	}
	cout << ans << '\n';
}

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

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

你可能感兴趣的:(2024寒假训练记录,深度优先,算法)