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






浙公网安备 33010602011771号