Loading

AtCoder Beginner Contest 396



A - Triple Four

题意

思路

模拟

代码

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;

const int mxn = 2e5 + 10;

void solve()
{
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}
	for (int i = 0; i < n - 2; i++)
	{
		if (a[i] == a[i + 1] && a[i] == a[i + 2])
		{
			cout << "Yes" << endl;
			return;
		}
	}
	cout << "No" << endl;


}

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

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

	return 0;
}

B - Card Pile

题意

思路

模拟

代码

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;

const int mxn = 2e5 + 10;

void solve()
{
	int q;
	cin >> q;
	stack<int> s;
	for (int i = 0; i < 100; i++)
	{
		s.push(0);
	}
	while (q--)
	{
		int op;
		cin >> op;
		if (op == 1)
		{
			int x;
			cin >> x;
			s.push(x);
		}
		else
		{
			cout << s.top() << endl;
			s.pop();
		}
	}


}

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

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

	return 0;
}

C - Buy Balls

题意

思路

两种球降序排序,对于非负数一定要选(在保证黑球数量不少于白球时);剩下的和非负就选

代码

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;

const int mxn = 2e5 + 10;

void solve()
{
	int n, m;
	cin >> n >> m;
	vector<int> b(n), w(m);
	for (int i = 0; i < n; i++)
	{
		cin >> b[i];
	}
	for (int i = 0; i < m; i++)
	{
		cin >> w[i];
	}
	sort(b.begin(), b.end(), greater<int>());
	sort(w.begin(), w.end(), greater<int>());
	int ans = 0, i = 0, j = 0;
	while (i < n && b[i] >= 0)
	{
		ans += b[i++];
	}
	while (j < m && j < i && w[j] >= 0)
	{
		ans += w[j++];
	}
	while (i < n && j < m && b[i] + w[j] >= 0)
	{
		ans += b[i++] + w[j++];
	}
	cout << ans << endl;
}

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

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

	return 0;
}

D - Minimum XOR Path

题意

思路

\(n\)只有\(10\)?爆!!

代码

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;

const int mxn = 10 + 10;

int n, m, ans = LLONG_MAX;
vector<vector<pii>> g;
bool vis[mxn];

void dfs(int u, int res)
{
	if (u == n)
	{
		ans = min(ans, res);
		return;
	}
	for (auto& [v, w] : g[u])
	{
		if (vis[v])
		{
			continue;
		}
		vis[v] = true;
		dfs(v, res ^ w);
		vis[v] = false;
	}
}

void solve()
{
	cin >> n >> m;
	g.resize(n + 1);
	for (int i = 1; i <= m; i++)
	{
		int u, v, w;
		cin >> u >> v >> w;
		g[u].push_back(make_pair(v, w));
		g[v].push_back(make_pair(u, w));
	}
	vis[1] = true;
	dfs(1, 0);
	cout << ans << endl;
}

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

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

	return 0;
}

E - Min of Restricted Sum

题意

思路

明显是个图论题——\((X_i,Y_i)\)间有权为\(Z_i\)的边,从\(X_i\)\(Y_i\)需要与\(Z_i\)相异或。由于边权的限制,每个连通分量的异或和是固定的,只需要在寻找连通分量的过程中检查是否有矛盾即可判断是否有解;要构造最小的\(A\)序列,就在每个连通分量中(大小为\(tot\))统计点每位\(1\)的个数,对于第\(i\)位,若有\(k\)个点是\(1\),令该位为\(1\)的贡献为\(k×2^i\),令该位为\(0\)的贡献为\((tot-k)×2^k\),取小的一个。

代码

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;

const int mxn = 2e5 + 10;

int n, m, f = true, tot;
vector<vector<pii>> g;
int sum[mxn], a[mxn], bit[32];
bool vis[mxn];

void dfs1(int u, int now)
{
	if (!f)
	{
		return;
	}
	tot++;
	for (int i = 0; i < 32; i++)
	{
		if (now >> i & 1)
		{
			bit[i]++;
		}
	}
	vis[u] = true;
	for (auto& [v, w] : g[u])
	{
		if (vis[v])
		{
			if (sum[v] != (now ^ w))
			{
				f = false;
				return;
			}
		}
		else
		{
			sum[v] = now ^ w;
			dfs1(v, now ^ w);
		}
	}
}

void dfs2(int u)
{
	vis[u] = true;
	for (auto& [v, w] : g[u])
	{
		if (vis[v])
		{
			continue;
		}
		a[v] = a[u] ^ w;
		dfs2(v);
	}
}

void solve()
{
	cin >> n >> m;
	g.resize(n + 1);
	for (int i = 0; i < m; i++)
	{
		int u, v, w;
		cin >> u >> v >> w;
		g[u].push_back(make_pair(v, w));
		g[v].push_back(make_pair(u, w));
	}
	for (int i = 1; i <= n; i++)
	{
		if (!vis[i])
		{
			tot = 0;
			fill(bit, bit + 32, 0);
			dfs1(i, 0);
			if (!f)
			{
				cout << -1 << endl;
				return;
			}
			for (int j = 0; j < 32; j++)
			{
				// 确定每个连通块的起点值
				if (bit[j] > tot - bit[j])
				{
					a[i] |= 1LL << j; 
				}
			}
		}
	}
	fill(vis, vis + n + 1, false);
	for (int i = 1; i <= n; i++)
	{
		if (!vis[i])
		{
			dfs2(i);
		}
	}
	for (int i = 1; i <= n; i++)
	{
		cout << a[i] << " ";
	}
}

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

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

	return 0;
}

F - Rotated Inversions

题意

给定正整数\(n,m\)和长度为\(n\)的非负整数序列\(A\)
对于\(k=-,1,...,m-1\),求解下列问题:
定义一个长度为\(n\)的整数序列\(B\),使得\(B_i\equiv (A_i+k)\ mod\ m\)。求\(B\)中的逆序对

思路

注意到如果\(B_i = A_i + k\),不取模,那\(B\)中逆序对的数量就是\(A\)中逆序对的数量,这个时候\(k=0\)。也就是说,只有当某个\(B_i\)因取模变成\(0\)时,它前后的逆序对才会发生变化,此时\(B_i = m - k\),而其他没有变成\(0\)的数一定比\(B_i\)小。当\(B_i\)变成\(0\)后,其前后的数都大于\(B_i\)(除了与\(B_i\)相同的数),此时就可以计算逆序对的变化。详情见代码
逆序对的计算:归并排序、树状数组 (都是\(O(n\ log\ n)\))

代码

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;

const int mxn = 2e5 + 10;

int t[mxn];
int n, m, ans;

inline int lowbit(int x)
{
	return x & -x;
}

int query(int l, int r)
{
	int res = 0;
	for (int i = r; i; i -= lowbit(i))
	{
		res += t[i];
	}
	for (int i = l - 1; i; i -= lowbit(i))
	{
		res -= t[i];
	}
	return res;
}

void update(int p, int x)
{
	for (int i = p; i <= n; i += lowbit(i))
	{
		t[i] += x;
	}
}

void solve()
{
	cin >> n >> m;
	vector<pii> inv;
	vector<vector<int>> pos(m + 1);
	for (int i = 1; i <= n; i++)
	{
		int x;
		cin >> x;
		pos[x].push_back(i);
		inv.push_back(make_pair(x, i));
	}
	// 求当 k = 0 时的逆序对
	sort(inv.begin(), inv.end(), greater<pii>());
	for (auto& [x, i] : inv)
	{
		ans += query(1, i);
		update(i, 1);
	}
	cout << ans << endl;
	for (int k = 1; k < m; k++)
	{
		int a = m - k;
		for (int i = 0; i < pos[a].size(); i++) // 只有 a = m - k 的会影响逆序对
		{
			// 由于对于不等于 m - k 的数,一定比 a 小
			// 在 a 之前除去等于 a 的一定会增加逆序对数
			ans += pos[a][i] - 1 - i;
			// 反之 a 之后的会减少
			ans -= n - pos[a][i] - (int)pos[a].size() + i + 1;
		}
		cout << ans << endl;
	}
}

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

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

	return 0;
}


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

posted @ 2025-03-08 23:12  _SeiI  阅读(106)  评论(0)    收藏  举报