A. X Axis
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define int long long
const int N = 1e6 + 10;
typedef pair<int, int> pii;
int a[4];
void solve()
{
cin >> a[1] >> a[2] >> a[3];
sort (a + 1, a + 4);
cout << a[3] - a[1] << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_ -- )
{
solve();
}
return 0;
}
B. Matrix Stabilization
think: 对于每个格子如果它周围的四个格子的数存在小于它的话,当前格子保持不变。反之,如果周围四个格子都小于它,当前格子的值为周围四个格子中的最大值。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define int long long
const int N = 1e6 + 10;
typedef pair<int, int> pii;
int n, m;
int a[110][110];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int check(int x, int y) {
bool ok = 0;
vector<int> b(4);
for (int i = 0; i < 4; i ++ ) {
int xx = x + dx[i], yy = y + dy[i];
b[i] = a[xx][yy];
if (a[xx][yy] > a[x][y]) {
return a[x][y];
}
}
sort (b.begin(), b.end());
return b[3];
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n + 1; i ++ ) {
for (int j = 1; j <= m + 1; j ++ ) {
a[i][j] = 0;
}
}
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
cin >> a[i][j];
}
}
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
a[i][j] = check(i, j);
}
}
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
cout << a[i][j] << ' ';
}
cout << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_ -- )
{
solve();
}
return 0;
}
C. Update Queries
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define int long long
const int N = 1e6 + 10;
typedef pair<int, int> pii;
int n, m;
string s, t;
void solve()
{
cin >> n >> m >> s;
set<int> S;
for (int i = 1; i <= m; i ++ ) {
int x;
cin >> x;
S.insert(x);
}
vector<char> g;
for (int i = 1; i <= m; i ++ ) {
char c;
cin >> c;
g.emplace_back(c);
}
sort (g.begin(), g.end());
int now = 0;
for (auto x : S) {
s[x - 1] = g[now ++];
}
cout << s << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_ -- )
{
solve();
}
return 0;
}
D. Mathematical Problem
think:本题是在n个数中间添加n-2个符号,所以我们可以先枚举这n个数中是哪两个数中间没符号。然后,就变成了在n-1个数中间添加n-2个符号,显然如果这n-1个数中出现0的话,答案就是0(因为0乘以任何数都是0)。最后如果相邻两个数其中有一个数小于等于1的话,这两个数之间肯定用+会更优,反之用*号。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define int long long
const int N = 1e6 + 10;
typedef pair<int, int> pii;
int n, ans;
string s;
void solve()
{
cin >> n >> s;
ans = 4557430888798830398;
for (int i = 0; i < n - 1; i ++ ) {
vector<int> alls;
for (int j = 0; j < n; j ++ ) {
if (j == i) {
string now = s.substr(j, 2);
j ++;
int t = stoi(now);
if (! t) {
cout << 0 << '\n';
return ;
}
alls.emplace_back(t);
} else {
string now = s.substr(j, 1);
int t = stoi(now);
if (! t) {
cout << 0 << '\n';
return ;
}
alls.emplace_back(t);
}
}
int sum = 0;
for (int i = 0; i < alls.size() - 1; i ++ ) {
if (alls[i] < 2 || alls[i + 1] < 2) {
alls[i + 1] *= alls[i];
alls[i] = 0;
}
}
for (int i = 0; i < alls.size(); i ++ ) {
sum += alls[i];
}
ans = min(ans, sum);
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_ -- )
{
solve();
}
return 0;
}
E. Beautiful Array
think:先对所有的数模k进行分组,然后如果有不小于2个组数量为奇数个那就是无解的。然后对于其中某个组来说,先对组内元素进行排序。如果是偶数个数的话,按照(1,2),(3,4)......(n-1, n)这样匹配肯定是最优的。如果是奇数个数的话,先枚举删哪个数,然后用前后缀和算一下答案就行。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define int long long
const int N = 1e6 + 10;
typedef pair<int, int> pii;
int n, k, a[N];
vector<int> alls;
int find(int y) {
return lower_bound(alls.begin(), alls.end(), y) - alls.begin() + 1;
}
void solve()
{
cin >> n >> k;
alls.clear();
vector<int> g[n + 1];
bool ok = 0;
int cnt = 0, ans = 0;
for (int i = 1; i <= n; i ++ ) {
cin >> a[i];
alls.push_back(a[i] % k);
}
// 离散化
sort (alls.begin(), alls.end());
alls.erase(unique(alls.begin(), alls.end()), alls.end());
for (int i = 1; i <= n; i ++ ) {
int t = find(a[i] % k);
g[t].emplace_back(a[i]);
}
for (int i = 0; i < alls.size(); i ++ ) {
if (g[i].size() % 2 == 1) cnt ++;
}
if (n % 2 == 0 && cnt || cnt >= 2) {
cout << -1 << '\n';
return ;
}
for (int i = 1; i <= alls.size(); i ++ ) {
// cout << i << ' ' << g[i].size() << '\n';
sort (g[i].begin(), g[i].end());
if (g[i].size() % 2 == 0) {
for (int j = 0; j <= g[i].size() - 2; j += 2) {
ans += (g[i][j + 1] - g[i][j]) / k;
}
} else {
// cout << g[i].size() << '\n';
// for (int j = 0; j < g[i].size(); j ++ ) {
// cout << g[i][j] << ' ';
// }
// cout << endl;
vector<int> pre(g[i].size() + 10, 0), last(g[i].size() + 10, 0);
for (int j = 1; j < g[i].size(); j += 2) {
pre[j] = (j - 2 >= 0 ? pre[j - 2] : 0) + g[i][j] - g[i][j - 1];
}
for (int j = g[i].size() - 2; j >= 0; j -= 2) {
last[j] = (j + 2 < g[i].size() ? last[j + 2] : 0) + g[i][j + 1] - g[i][j];
}
int ma = 4e18;
for (int j = 0; j < g[i].size(); j += 2) {
int t = (j > 0 ? pre[j - 1] : 0) + (last[j + 1]);
ma = min(ma, t);
}
ans += ma / k;
}
// cout << ' ' << ans <<'\n';
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_ -- )
{
solve();
}
return 0;
}
F. Non-academic Problem
think:本题是要求删掉一条边之后,能到达的点对数量最少。首先,进行缩点。然后对于其中非桥的边,删掉之后连通性不会改变,所以能到达的点对数量不会变化。然后对于桥来说,删掉之后会把缩完点之后的图分成两个连通块。统计下两个连通块中能到达的点对数量即可。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define int long long
const int N = 1e6 + 10;
typedef pair<int, int> pii;
int n, m, tim, cnt, now, ans;
int dfn[N], low[N], sz[N], bel[N], nsz[N], vis[N];
vector<pii> g[N];
vector<int> cc[N];
stack<int> stk;
void tarjan(int u, int id) {
dfn[u] = low[u] = ++ tim;
stk.push(u);
for (auto [v, id2] : g[u]) {
if (! dfn[v]) {
tarjan(v, id2);
low[u] = min(low[u], low[v]);
} else if (id != id2) {
low[u] = min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
++ cnt;
while (true) {
int v = stk.top();
stk.pop();
bel[v] = cnt;
cc[cnt].push_back(v);
sz[cnt] ++;
if (v == u) break;
}
ans = min(ans, nsz[u] * (nsz[u] - 1) / 2 + (n - nsz[u]) * (n - nsz[u] - 1) / 2);
}
}
void dfs(int u, int fa) {
nsz[u] += 1;
vis[u] = 1;
for (auto [v, id] : g[u]) {
if (v == fa) continue;
if (vis[v]) continue;
dfs(v, u);
nsz[u] += nsz[v];
}
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) {
dfn[i] = low[i] = sz[i] = bel[i] = vis[i] = 0, nsz[i] = 0;
g[i].clear();
}
cnt = tim = now = 0;
while (stk.size()) stk.pop();
ans = n * (n - 1) / 2;
for (int i = 1; i <= m; i ++ ) {
int u, v;
cin >> u >> v;
g[u].push_back({v, i});
g[v].push_back({u, i});
}
dfs(1, 0);
for (int i = 1; i <= 1; i ++ ) {
if (! dfn[i]) {
tarjan(i, -1);
}
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_ -- )
{
solve();
}
return 0;
}