2024.1.27 寒假训练记录(10)

下午训练赛的榜歪得吓人,来补一下题。

文章目录

  • CF 1646B Quality vs Quantity
  • CF 1326C Permutation Partitions
  • CF 1355D Game With Array
  • AT ARC99B Snuke Numbers
  • AT exawizards2019C Snuke the Wizard
  • CF 1788F XOR, Tree, and Queries

CF 1646B Quality vs Quantity

题目链接

双指针两端遍历即可

#include 

using namespace std;

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

void solve()
{
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i ++ ) cin >> a[i];
	sort(a.begin(), a.end());
	int i = 2, j = n - 2;
	int sum1 = a[0] + a[1], sum2 = a[n - 1];
	int cnt1 = 2, cnt2 = 1;
	while (i <= j)
	{
		if (sum1 < sum2 && cnt1 > cnt2)
		{
			cout << "YES\n";
			return;
		}
		else if (sum1 >= sum2)
		{
			sum2 += a[j];
			cnt2 ++ ;
			j -- ;
		}
		else if (cnt1 <= cnt2)
		{
			sum1 += a[i];
			cnt1 ++ ;
			i ++ ;
		}
	}
	if (sum1 < sum2 && cnt1 > cnt2)
	{
		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();
	}
}

CF 1326C Permutation Partitions

题目链接

每个区间分一个前k大的数就行了,剩下就是简单组合数学

#include 

using namespace std;

#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;
	vector<PII> a(n);
	for (int i = 0; i < n; i ++ )
	{
		a[i].second = i;
		cin >> a[i].first;
	}
	sort(a.begin(), a.end());
	int ans = 0;
	for (int i = n - 1; i >= n - k; i -- ) ans += a[i].first;
	int cnt = 1;
	vector<int> tmp;
	for (int i = n - 1; i >= n - k; i -- ) tmp.push_back(a[i].second);
	sort(tmp.begin(), tmp.end());
	for (int i = 1; i < tmp.size(); i ++ ) cnt = cnt * (tmp[i] - tmp[i - 1]) % mod;
	cout << ans << ' ' << cnt << '\n';
}

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

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

CF 1355D Game With Array

题目链接

前面全取1,后面取S-(n-1)即可

主要思路是让能被替代的数尽可能多,如果是1 2 4 8这种取法,互相之间不能被替代,所以能够组成的数就多了

#include 

using namespace std;

#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,s;
	cin >> n >> s;
	if (2 * n > s)
	{
		cout << "NO\n";
		return;
	}
	cout << "YES\n";
	for (int i = 0; i < n - 1; i ++ ) cout << 1 << ' ';
	cout << s - (n - 1) << '\n';
	cout << s - n << '\n';
}

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

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

AT ARC99B Snuke Numbers

题目链接

打表找规律(这么有意思的题到底哪里毒瘤了 ^ _ ^

#include 

using namespace std;

#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 k;
	cin >> k;
	int d = 1;
	int ans = 0;
	auto sum = [&](int x)
	{
		string s = to_string(x);
		int res = 0;
		for (int i = 0; i < s.size(); i ++ )
		{
			res += s[i] - '0';
		}
		return res;
	};
	for (int i = 0; i < k; i ++ )
	{
		if ((ans + d * 10) * sum(ans + d) < (ans + d) * sum(ans + d * 10)) d *= 10;
		ans += d;
		cout << ans << '\n';
	}
}

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

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

AT exawizards2019C Snuke the Wizard

题目链接

二分左右边界即可

二分的时候可以修改条件来保证一定能找到你想找到的值,否则可能会出现没有符合条件的点的情况

#include 

using namespace std;

#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, q;
	cin >> n >> q;
	string s;
	cin >> s;
	s = " " + s;
	vector<char> t(q), d(q);
	for (int i = 0; i < q; i ++ ) cin >> t[i] >> d[i];

	auto check = [&](int x)
	{
		for (int i = 0; i < q; i ++ )
		{
			if (t[i] == s[x])
			{
				if (d[i] == 'L') x -- ;
				else x ++ ;
				if (x <= 0) return 0;
				else if (x > n) return 1;
			}
		}
		return 2;
	};

	int l = 0, r = n + 1;
	while (l < r)
	{
		int mid = l + r + 1 >> 1;
		if (check(mid) == 0) l = mid;
		else r = mid - 1;
	}
	int ansl = r;

	l = 0, r = n + 1;
	while (l < r)
	{
		int mid = l + r >> 1;
		if (check(mid) == 1) r = mid;
		else l = mid + 1;
	}
	int ansr = r;

	cout << ansr - ansl - 1 << '\n';
}

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

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

CF 1788F XOR, Tree, and Queries

题目链接

p[i]i到根结点的边权值异或和,根据异或的性质可以得到点uv的边权异或和就是p[u] ^ p[v]

输入边的时候记录点的度数,度数为偶数的可以不用管,因为会相抵消

根据已给的边权信息,可以利用dfs得到一组可行解(设每个连通块遍历的第一个点wp[w] = 0),同时在遍历的时候发现矛盾直接返回NO

之后就是让所有边权异或和最小了,先记录所有度为奇数的点的异或和为ans,连通块点数为偶数的,异或值会相抵消不用管,只要遇见奇数,只需要让连通块中的点与当前ans取异或就行

#include 

using namespace std;

#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, m;
	cin >> n >> m;
	vector<PII> edge(n - 1);
	vector<int> du(n + 1), p(n + 1), size(n + 1), root(n + 1);
	for (int i = 0; i < n - 1; i ++ )
	{
		cin >> edge[i].first >> edge[i].second;
		du[edge[i].first] ++ , du[edge[i].second] ++ ;
	}
	
	vector<vector<PII>> g(n + 1);
	for (int i = 0; i < m; i ++ )
	{
		int a, b, c;
		cin >> a >> b >> c;
		g[a].push_back(make_pair(b, c));
		g[b].push_back(make_pair(a, c));
	}

	function<void(int, int)> dfs = [&](int u, int rt)
	{
		root[u] = rt;
		for (int i = 0; i < g[u].size(); i ++ )
		{
			int j = g[u][i].first;
			if (!root[j])
			{
				p[j] = (p[u] ^ g[u][i].second);
				dfs(j, rt);
			}
			else if (p[j] != (p[u] ^ g[u][i].second))
			{
				cout << "NO\n";
				exit(0);
			}
		}
	};

	for (int i = 1; i <= n; i ++ )
	{
		if (root[i]) continue;
		dfs(i, i);
	}

	int ans = 0;
	for (int i= 1; i <= n; i ++ ) 
	{
		if (du[i] % 2 != 0)
		{
			ans ^= p[i];
			size[root[i]] ++ ;
		}
	}

	for (int i = 1; i <= n; i ++ )
	{
		if (size[i] % 2 == 0) continue;
		for (int j = 1; j <= n; j ++ )
		{
			if (root[j] == i) p[j] ^= ans;
		}
		break;
	}

	cout << "YES\n";
	for (int i = 0; i < n - 1; i ++ )
	{
		cout << (p[edge[i].first] ^ p[edge[i].second]) << ' ';
	}
	cout << '\n';
}

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

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

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