2024.4.15-4.21 训练记录(27)

  • 周末要打天梯赛和蓝桥杯,过了这周总算事情少一点了
  • 最近精神内耗好严重

ATC - abc348

A - Penalty Kick

输出题

#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i ++ )
	{
		if (i % 3 == 0) cout << 'x';
		else cout << 'o';
	}
}

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

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

B - Farthest Point

纯暴力

#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

int dist(int x1, int y1, int x2, int y2)
{
	return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
}

void solve()
{
	int n;
	cin >> n;
	vector<PII> a(n);
	for (int i = 0; i < n; i ++ ) cin >> a[i].first >> a[i].second;
	for (int i = 0; i < n; i ++ )
	{
		int maxx = 0, pos = -1;
		for (int j = 0; j < n; j ++ )
		{
			if (dist(a[i].first, a[i].second, a[j].first, a[j].second) > maxx) maxx = dist(a[i].first, a[i].second, a[j].first, a[j].second), pos = j;
		}
		cout << pos + 1 << '\n';
	}
}

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

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

C - Colorful Beans

暴力,找到每种颜色最小值里的最大值

#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<int, string> PIS;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;


void solve()
{
	int n;
	cin >> n;
	map<int, vector<int>> mp;
	for (int i = 0; i < n; i ++ )
	{
		int a, c;
		cin >> a >> c;
		mp[c].push_back(a);
	}
	int ans = 0;
	for (auto t : mp)
	{
		sort(t.second.begin(), t.second.end());
		ans = max(ans, t.second[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();
	}
}

D - Medicines on Grid(dijkstra)

一开始把题目看错了,走到有药品的格子,是把自身能量变成药品值

那就很简单了,在 dijkstra 更新状态的时候更新一下如果当前格有药品的情况即可

#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<int, string> PIS;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};

void solve()
{
	int h, m;
	cin >> h >> m;
	vector<vector<char>> g(h + 1, vector<char>(m + 1));
	int stx, sty, edx, edy;
	for (int i = 1; i <= h; i ++ )
	{
		for (int j = 1; j <= m; j ++ )
		{
			cin >> g[i][j];
			if (g[i][j] == 'S') stx = i, sty = j;
			if (g[i][j] == 'T') edx = i, edy = j;
		}
	}
	int n;
	cin >> n;
	vector<vector<int>> w(h + 1, vector<int>(m + 1));
	vector<vector<int>> dist(h + 1, vector<int>(m + 1, -1));
	for (int i = 0; i < n; i ++ ) 
	{
		int r, c, e;
		cin >> r >> c >> e;
		w[r][c] += e;
	}
	priority_queue<PIII> pq;
	if (w[stx][sty] == 0)
	{
		cout << "No\n";
		return;
	}
	pq.push({w[stx][sty], {stx, sty}});
	while (pq.size())
	{
		auto t = pq.top();
		pq.pop();

		int ery = t.first, x = t.second.first, y = t.second.second;

		if (dist[x][y] < w[x][y])
		{
			dist[x][y] = w[x][y];
			pq.push({dist[x][y], {x, y}});
			continue;
		}

		for (int i = 0; i < 4; i ++ )
		{
			int nx = x + dx[i], ny = y + dy[i];
			if (nx <= 0 || nx > h || ny <= 0 || ny > m) continue;
			if (st[nx][ny] || g[nx][ny] == '#') continue;

			if (dist[nx][ny] < ery - 1)
			{
				dist[nx][ny] = ery - 1;
				pq.push({dist[nx][ny], {nx, ny}});
			}
		}
	}
	if (dist[edx][edy] == -1) cout << "No\n";
	else cout << "Yes\n";
}

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

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

E - Minimize Sum of Distances(换根dp)

还算是比较典的换根dp(能让我看出来那就是非常典的换根dp

先跑一遍dfs处理每个结点子树的大小

然后计算选择第一个点的答案

f[i] 表示第 i 个点为根的答案

换之前的根是 u,换之后的是 ver,从 u 换到 ver ,所有在 ver 子树中的结点到根的距离加一,其他结点到根的距离减一

#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<int, string> PIS;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
	int n;
	cin >> n;
	vector<vector<int>> g(n + 1);
	for (int i = 0; i < n - 1; i ++ )
	{
		int u, v;
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	vector<int> c(n + 1), sz(n + 1), dist(n + 1, INF);
	for (int i = 1; i <= n; i ++ ) cin >> c[i];
	function<void(int, int)> dfs1 = [&](int u, int fa)
	{
		sz[u] = c[u];
		for (int i = 0; i < g[u].size(); i ++ )
		{
			int j = g[u][i];
			if (j == fa) continue;
			dfs1(j, u);
			sz[u] += sz[j];
		}
	};
	dfs1(1, -1);

	dist[1] = 0;
	queue<int> q;
	q.push(1);
	while (q.size())
	{
		auto t = q.front();
		q.pop();

		for (int i = 0; i < g[t].size(); i ++ )
		{
			int ver = g[t][i];
			if (dist[ver] > dist[t] + 1)
			{
				dist[ver] = dist[t] + 1;
				q.push(ver);
			}
		}
	}

	int ans = INF;
	vector<int> f(n + 1, INF);
	f[1] = 0;
	for (int i = 1; i <= n; i ++ ) f[1] += c[i] * dist[i];

	function<void(int, int)> dfs2 = [&](int u, int fa)
	{
		ans = min(ans, f[u]);
		for (int i = 0; i < g[u].size(); i ++ )
		{
			int ver = g[u][i];
			if (ver == fa) continue;
			f[ver] = min(f[ver], f[u] - sz[ver] + sz[1] - sz[ver]);
			dfs2(ver, u);
		}
	};
	dfs2(1, -1);
	cout << ans << '\n';
}

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

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

F - Oddly Similar(bitset优化)

计算不同状态的个数,且状态只有两种,可以利用bitset

#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<int, string> PIS;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
	int n, m;
	cin >> n >> m;
	vector<vector<int>> g(n, vector<int>(m));
	vector<vector<bitset<2010>>> a(m, vector<bitset<2010>>(1010));
	for (int i = 0; i < n; i ++ )
	{
		for (int j = 0; j < m; j ++ )
		{
			int x; cin >> x;
			g[i][j] = x;
			a[j][x][i] = 1;
		}
	}
	int ans = 0;
	for (int i = 0; i < n; i ++ )
	{
		bitset<2010> bt = {};
		for (int j = 0; j < m; j ++ )
		{
			bt ^= a[j][g[i][j]];
		}
		bt[i] = 0;
		ans += bt.count();
	}
	cout << ans / 2 << '\n';
}

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

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

G - Max (Sum - Max)(主席树+二分)

很明显先按b排序,然后枚举b,再找b和b之前对应的a中最大的k个值,这个用主席树维护

同时这里又有个二分性,如果在前 j 个 b 中我们选择了第 i 个 b ,那么我们称 i 是对于 j 的最优决策点,可以发现,最优决策点一定是非递减的,所以套个二分处理(其实这里也没有理解的很好,但主席树真的调了超级无敌久)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 10, INF = 1000000000, inf = 1e18;

struct node {
    int ls, rs;
    int sz;
    int sum;
};

node tr[N * 35];
int idx = 0;
int rt[N];
int n, ans[N];
pair<int, int> v[N];
bool cmp(PII x, PII y)
{
	return x.second < y.second;
}
int add(int p, int l, int r, int x)
{ // 插入
	int q = ++ idx;
	if (p != 0)  tr[q] = tr[p];
	if (l == r)
	{
		tr[q].sz += 1;
		tr[q].sum += x;
		return q;
	}
	int mid = l + r >> 1;
	if (x <= mid) tr[q].ls = add(tr[p].ls, l, mid, x);
	else tr[q].rs = add(tr[p].rs, mid + 1, r, x);
	tr[q].sz = tr[tr[q].ls].sz + tr[tr[q].rs].sz;
	tr[q].sum = tr[tr[q].ls].sum + tr[tr[q].rs].sum;
	return q;
}

int query(int p, int l, int r, int k)
{
	if (p == 0) return 0;
	if (l == r) return l * k;
	int mid = l + r >> 1;
	if (tr[tr[p].rs].sz >= k) return query(tr[p].rs, mid + 1, r, k);
	else return tr[tr[p].rs].sum + query(tr[p].ls, l, mid, k - tr[tr[p].rs].sz);
}
int ask(int k, int x)
{
	return query(rt[x - 1], -INF, INF, k - 1) + v[x].first - v[x].second;
}
void work(int l, int r, int L, int R)
{
	if (l > r) return;
	int mid = l + r >> 1;
	ans[mid] = -inf;
	int pos;
	for (int i = max(mid, L); i <= R; i ++ )
	{
		int tmp = ask(mid, i);
		if (tmp > ans[mid]) ans[mid] = tmp, pos = i;
	}
	work(l, mid - 1, L, pos);
	work(mid + 1, r, pos, R);
}
signed main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> v[i].first >> v[i].second;
	}
	sort(v + 1, v + 1 + n, cmp);

	for (int i = 1; i <= n; i++)
	{
		rt[i] = add(rt[i - 1], -INF, INF, v[i].first);
	}
	work(1, n, 1, n);
	for (int i = 1; i <= n; i++)
	{
		cout << ans[i] << endl;
	}
	return 0;
}

CF-1286B-Numbers on Tree

题目链接

有意思的构造,构造题还是容易想复杂啊

想到了把每个点赋值 [1, n],但是没注意到 n 挺小的完全暴力查找就可以,一直在想怎么二分找值。。。

树上构造的大致思路还是dfs构造单点

#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
	int n;
	cin >> n;
	vector<int> p(n + 1), c(n + 1);
	vector<vector<int>> g(n + 1);
	int root = 0;
	for (int i = 1; i <= n; i ++ )
	{
		cin >> p[i] >> c[i];
		g[p[i]].push_back(i);
		if (p[i] == 0) root = i;
	}
	vector<int> sz(n + 1);
	function<void(int, int)> dfs1 = [&](int u, int fa)
	{
		sz[u] = 1;
		for (int i = 0; i < g[u].size(); i ++ )
		{
			int j = g[u][i];
			if (j == fa) continue;
			dfs1(j, u);
			sz[u] += sz[j];
		}
	};
	dfs1(root, -1);
	vector<int> ans(n + 1);
	vector<int> st(n + 1);
	auto find_a = [&](int x)
	{
		int cnt = 0;
		for (int i = 1; i <= n; i ++ )
		{
			if (!st[i])
			{
				cnt ++ ;
				if (cnt == x + 1)
				{
					st[i] = true;
					return i;
				}
			}
		}
		return (i64)-1;
	};
	function<bool(int, int)> dfs2 = [&](int u, int fa)
	{
		int tmp = find_a(c[u]);
		if (tmp == -1) return false;
		if (sz[u] - 1 < c[u]) return false;
		ans[u] = tmp;
		for (int i = 0; i < g[u].size(); i ++ )
		{
			int ver = g[u][i];
			if (ver == fa) continue;
			if (!dfs2(ver, u)) return false;
		}
		return true;
	};
	if (dfs2(root, -1))
	{
		cout << "YES\n";
		for (int i = 1; i <= n; i ++ ) cout << ans[i] << ' ';
	}
	else cout << "NO\n";
}

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

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

ATC - abc350

C - Airport Code

暴力判断

#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
	string s, t;
	cin >> s >> t;
	int flag = 0;
	for (int i = 0; i < s.size(); i ++ )
	{
		if (s[i] >= 'a' && s[i] <= 'z') s[i] += 'A' - 'a';
		if (s[i] == t[flag]) flag ++ ;
		if (flag == 3)
		{
			cout << "Yes\n";
			return;
		}
	}
	if (flag == 2 && t[2] == 'X') cout << "Yes\n";
	else cout << "No\n";
}

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

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

D - Divide Interval(贪心)

首先很容易想到要让每个 2 i 2^i 2i 尽可能大(所以 j × 2 i j\times2^i j×2i 里的 j 必须是奇数,因为偶数可以直接再出一个2),但让 2 i 2^i 2i 尽可能大的同时不要忘了让 l + 2 i l+2^i l+2i 不超过 r r r,找到同时满足这两个条件的一个数,再往后贪心下去

#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
	int l, r;
	cin >> l >> r;
	vector<PII> ans;
	while (l < r)
	{
		int p1 = 1;
		int p2 = l;
		while (p2 % 2 == 0 && l + p1 <= r)
		{
			p2 /= 2;
			p1 *= 2;
		}
		while (l + p1 > r)
		{
			p1 /= 2;
		}
		ans.push_back({l, l + p1});
		l = l + p1;
	}
	cout << ans.size() << '\n';
	for (auto t : ans) cout << t.first << ' ' << t.second << '\n';
}

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

	int t = 1;
	// cin >> t;
	while (t--)
	{
		solve();
	}
}
  • 13
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Texcavator

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值