SMU Summer 2024 Contest Round 6
SMU Summer 2024 Contest Round 6
Many Formulas
题意
给你一个数,你可以在这个数的任意位之间插入零个或多个+
号,形成一个算式,你需要计算所有可能形成的算式的和。
思路
因为 \(1\le |S|\le10\),考虑暴力。
一个 n 位数,最多可以在 n-1 个空位插入加号,二进制枚举即可。
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
i64 n;
cin >> n;
string s = to_string(n);
const int sz = s.size() - 1;
i64 ans = 0;
for (int i = 0; i < (1 << sz); i++) {
i64 nxt = 0;
for (int j = 0; j < s.size(); j ++) {
if (((i >> j) & 1) || j + 1 == s.size()) {
i64 res = stoll(s.substr(nxt, j - nxt + 1));
ans += res;
nxt = j + 1;
}
}
}
cout << ans << '\n';
return 0;
}
Tak and Cards
题意
给你 n 个数和一个数 A,你需要从中选出一些数使得其凑成的平均数为 A,问你这样的选数方案有多少种。
思路
n 个数选数,考虑背包。
这里还有一个问题,就是因为它是平均数,对于一个数作为平均数,它可能是 4 个数平均下来的,也可能是 3 个数平均下来的,所以我们要多开一维去记录这个数是由几个数平均下来的。
设 \(dp_{i,j}\) 为 i 个数凑成 j 的方案数。
然后就是去跑背包的时候注意为了去掉后效性要 i 个数要倒着跑,最后的答案就是 \(\sum_i^ndp_{i,i\times A}\)。
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, A;
cin >> n >> A;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++)
cin >> a[i];
const int N = 2500;
vector dp(n + 1, vector<i64>(N + 1));
sort(a.begin() + 1, a.end());
dp[0][0] = 1;
for (int k = 1; k <= n; k ++)
for (int i = k; i >= 1; i --) {
for (int j = N; j >= a[k]; j --) {
dp[i][j] += dp[i - 1][j - a[k]];
}
}
i64 ans = 0;
for (int i = 1; i <= n; i ++)
ans += dp[i][i * A];
cout << ans << '\n';
return 0;
}
Wall
题意
给你 \(10\times 10\) 的一个矩阵,代表 \(0\sim 9\) 互相转化的消耗,现给你一个 \(n\times m\) 的矩阵,问你把其中不是 -1 的数全部转化为 1 的最小消耗。
思路
先对这 \(0\sim 9\) 个数跑一遍 Floyd,求出每个数转成 1 的最小消耗,然后就是累加非 -1 的数转化成 1 的消耗即可。
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
const int N = 10;
int a[N][N] {};
for (int i = 0; i < 10; i ++)
for (int j = 0; j < 10; j ++)
cin >> a[i][j];
for (int k = 0; k < 10; k ++)
for (int i = 0; i < 10; i ++)
for (int j = 0; j < 10; j ++)
a[i][j] = min(a[i][j], a[i][k] + a[k][j]);
vector A(n, vector<int>(m));
i64 ans = 0;
for (auto &i : A)
for (auto &j : i) {
cin >> j;
if (j != -1) ans += a[j][1];
}
cout << ans << '\n';
return 0;
}
Coloring Edges on Tree
题意
给你一棵树,你需要给每条边染色,使得一个点所连的边中没有相同颜色的边,问你怎样给每条边染色。
思路
对于两个点,它们能互相影响的只有一条边,所以我们 dfs 跑一遍树,每次记录该点和它父节点所连边的颜色,又因为要让染色数最少,所以我们对该点的每一条边都从 1 开始染色,碰到和父节点相同的颜色就跳过即可。
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<array<int, 2>> edge(n);
map<pair<int, int>, int> ans;
vector g(n + 1, vector<int>());
for (int i = 1; i < n; i ++) {
int u, v;
cin >> u >> v;
edge[i] = {u, v};
g[u].push_back(v);
g[v].push_back(u);
}
set<int> Col;
auto dfs = [&](auto & self, int u, int fa, int x)->void{
int color = 1;
for (auto v : g[u]) {
if (v == fa)continue;
if (color == x)color++;
ans[ {u, v}] = ans[ {v, u}] = color;
Col.insert(color);
self(self, v, u, color);
color++;
}
};
dfs(dfs, 1, 0, 0);
cout << Col.size() << '\n';
for (int i = 1; i < n; i ++) {
auto [u, v] = edge[i];
cout << ans[ {u, v}] << '\n';
}
return 0;
}
Fault-tolerant Network
题意
现有 \(2×\) 台计算机分成两排,每排有 N 台,每台都有一定的价值,并且相邻的两台计算机之间通过网线连接。
现在请你在这两排之间接通一些网线,使得任意一台计算机坏掉后这些计算机还是连通的。
连接两台计算机的代价为 \(∣−∣\),\(,\) 分别表示这两台计算机的价值。
求出连通两排电脑的最小代价。
思路
手玩一些例子可以发现,对于 \(a_1,a_n,b_1,b_n\) 这四个点是必须要连着边的,因为对于这四个点中的哪个点,如果没有边与它相连,那么总是可以通过断掉它旁边的点来使它孤立。
那我们就从这四个点出发分类讨论:
- 考虑连两条边的情况,就是 a 的两个点与 b 的两个点两两互连。
- 考虑连三条边的情况,就是 a 的两个点与 b 的两个点只连其中一对,另外两个点连接 a 中或 b 中代价最小的边。
- 考虑连四条边的情况,就是四个点都连对面最小代价的边。
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
void solve() {
int n;
cin >> n;
vector<i64> a(n + 1), b(n + 1);
for (int i = 1; i <= n; i ++)
cin >> a[i];
for (int i = 1; i <= n; i ++)
cin >> b[i];
i64 ans = min(abs(a[1] - b[1]) + abs(a[n] - b[n]), abs(a[1] - b[n]) + abs(a[n] - b[1]));
i64 a1, an, b1, bn;
a1 = an = b1 = bn = INT_MAX;
for (int i = 1; i <= n; i ++) {
a1 = min(a1, abs(a[1] - b[i]));
an = min(an, abs(a[n] - b[i]));
b1 = min(b1, abs(b[1] - a[i]));
bn = min(bn, abs(b[n] - a[i]));
}
ans = min({ans, abs(a[1] - b[1]) + an + bn, abs(a[1] - b[n]) + an + b1, abs(a[n] - b[1]) + a1 + bn, abs(a[n] - b[n]) + a1 + b1});
ans = min(ans, a1 + an + b1 + bn);
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
Nearest Excluded Points
题意
给你一堆标记的点,你需要从坐标轴上找到非标记的点中离这些点曼哈顿距离最近的点。
思路
对于一个点,其离它曼哈顿距离最近的点肯定是它周围的四个点。
那么当一堆点合成一个块的时候,那么离这些点最近的曼哈顿距离最近的点也一定是这个块的周围的点,那我们可以用 bfs 将周围的这些非标记点作为起点去更新块中每层点的最近答案,初始非标记点的答案要更新为自己。
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<pair<int, int>> loc(n);
const int u[] = {1, -1, 0, 0}, v[] = {0, 0, 1, -1};
map<pair<int, int>, pair<int, int>> ans;
set<pair<int, int>> st;
queue<pair<int, int>> Q;
for (auto &[x, y] : loc) {
cin >> x >> y;
st.insert({x, y});
}
for (auto [x, y] : loc) {
for (int i = 0; i < 4; i ++) {
int dx = x + u[i], dy = y + v[i];
if (st.count({dx, dy})) continue;
Q.push({dx, dy});
ans[ {dx, dy}] = {dx, dy};
}
}
while (Q.size()) {
auto [x, y] = Q.front();
Q.pop();
for (int i = 0; i < 4; i ++) {
int dx = x + u[i], dy = y + v[i];
if (st.count({dx, dy})) {
ans[ {dx, dy}] = ans[ {x, y}];
Q.push({dx, dy});
st.erase({dx, dy});
}
}
}
for (auto node : loc) {
auto [x, y] = ans[node];
cout << x << ' ' << y << '\n';
}
return 0;
}
Vacation Query
题意
长度为 \(N\) 的 01 序列 \(S\),进行 \(Q\) 次操作:
1 L R
:将 \(S_L\) 到 \(S_R\) 每一位取反。2 L R
:求 \(S_L\) 到 \(S_R\) 的最长连续 1 串的长度。
思路
线段树维护最大子段和的模板题。
推荐题目:P2572 [SCOI2010] 序列操作 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
#define lc u << 1
#define rc u << 1 | 1
const int N = 1e5 + 5;
i64 w[N], n, m, p;
struct Tree { //线段树
int l, r;
int sum1, lmax1, rmax1, max1;
int sum0, lmax0, rmax0, max0;
int tag, rev;
} tr[N << 2];
void cal_lazy(int fa, int ch) {
int len = tr[ch].r - tr[ch].l + 1;
if (tr[fa].tag == 0) {
tr[ch].tag = 0, tr[ch].rev = 0;
tr[ch].sum0 = tr[ch].lmax0 = tr[ch].rmax0 = tr[ch].max0 = len;
tr[ch].sum1 = tr[ch].lmax1 = tr[ch].rmax1 = tr[ch].max1 = 0;
}
if (tr[fa].tag == 1) {
tr[ch].tag = 1, tr[ch].rev = 0;
tr[ch].sum0 = tr[ch].lmax0 = tr[ch].rmax0 = tr[ch].max0 = 0;
tr[ch].sum1 = tr[ch].lmax1 = tr[ch].rmax1 = tr[ch].max1 = len;
}
if (tr[fa].rev) {
tr[ch].rev ^= 1;
swap(tr[ch].sum1, tr[ch].sum0);
swap(tr[ch].lmax1, tr[ch].lmax0);
swap(tr[ch].rmax1, tr[ch].rmax0);
swap(tr[ch].max1, tr[ch].max0);
}
}
void tag_union(int fa, int ch) {
tr[ch].tag = tr[fa].tag;
tr[ch].rev ^= tr[fa].rev;
}
void init_lazy(int u) {
tr[u].tag = -1;
tr[u].rev = 0;
}
void pushdown(int u) {
if (tr[u].tag != -1 || tr[u].rev != 0) {
cal_lazy(u, lc);
cal_lazy(u, rc);
// tag_union(u, lc);
// tag_union(u, rc);
init_lazy(u);
}
}
void pushup(int u) { //上传
tr[u].sum1 = tr[lc].sum1 + tr[rc].sum1;
tr[u].sum0 = tr[lc].sum0 + tr[rc].sum0;
tr[u].lmax1 = tr[lc].lmax1 + (tr[lc].sum0 ? 0 : tr[rc].lmax1);
tr[u].rmax1 = tr[rc].rmax1 + (tr[rc].sum0 ? 0 : tr[lc].rmax1);
tr[u].lmax0 = tr[lc].lmax0 + (tr[lc].sum1 ? 0 : tr[rc].lmax0);
tr[u].rmax0 = tr[rc].rmax0 + (tr[rc].sum1 ? 0 : tr[lc].rmax0);
tr[u].max1 = max({tr[lc].max1, tr[rc].max1, tr[lc].rmax1 + tr[rc].lmax1});
tr[u].max0 = max({tr[lc].max0, tr[rc].max0, tr[lc].rmax0 + tr[rc].lmax0});
}
void build(int u, int l, int r) { //建树
tr[u].l = l, tr[u].r = r;
init_lazy(u);
if (l == r) {
int t = w[l];
tr[u] = {l, r, t, t, t, t, t ^ 1, t ^ 1, t ^ 1, t ^ 1, -1, 0};
return ;
}
int mid = (l + r) >> 1;
build(lc, l, mid);
build(rc, mid + 1, r);
pushup(u);
}
void modify(int u, int l, int r, int op) {
if (tr[u].l >= l && tr[u].r <= r) {
int len = tr[u].r - tr[u].l + 1;
if (op == 0) {
tr[u].rev = 0, tr[u].tag = 0;
tr[u].sum0 = tr[u].lmax0 = tr[u].rmax0 = tr[u].max0 = len;
tr[u].sum1 = tr[u].lmax1 = tr[u].rmax1 = tr[u].max1 = 0;
} else if (op == 1) {
tr[u].rev = 0, tr[u].tag = 1;
tr[u].sum0 = tr[u].lmax0 = tr[u].rmax0 = tr[u].max0 = 0;
tr[u].sum1 = tr[u].lmax1 = tr[u].rmax1 = tr[u].max1 = len;
} else {
tr[u].rev ^= 1;
swap(tr[u].sum1, tr[u].sum0);
swap(tr[u].lmax1, tr[u].lmax0);
swap(tr[u].rmax1, tr[u].rmax0);
swap(tr[u].max1, tr[u].max0);
}
return ;
}
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
if (l <= mid)
modify(lc, l, r, op);
if (r > mid)
modify(rc, l, r, op);
pushup(u);
}
Tree query(int u, int l, int r) { //区查
if (l <= tr[u].l && tr[u].r <= r)
return tr[u];
int mid = tr[u].l + tr[u].r >> 1;
pushdown(u);
if (r <= mid) return query(lc, l, r);
else if (l > mid) return query(rc, l, r);
else {
Tree res, L = query(lc, l, mid), R = query(rc, mid + 1, r);
res.sum1 = L.sum1 + R.sum1;
res.sum0 = L.sum0 + R.sum0;
res.lmax1 = L.lmax1 + (L.sum0 ? 0 : R.lmax1);
res.rmax1 = R.rmax1 + (R.sum0 ? 0 : L.rmax1);
res.lmax0 = L.lmax0 + (L.sum1 ? 0 : R.lmax0);
res.rmax0 = R.rmax0 + (R.sum1 ? 0 : L.rmax0);
res.max1 = max({L.max1, R.max1, L.rmax1 + R.lmax1});
res.max0 = max({L.max0, R.max0, L.rmax0 + R.lmax0});
return res;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
string s;
cin >> s;
for (int i = 1; i <= n; i ++)
w[i] = s[i - 1] - '0';
build(1, 1, n);
while (m--) {
int op, l, r;
cin >> op >> l >> r;
if (op == 1) {
modify(1, l, r, 2);
} else {
auto ans = query(1, l, r);
cout << ans.max1 << '\n';
}
}
return 0;
}
SMU Summer 2024 Contest Round 6的更多相关文章
- 2015 Astar Contest - Round 3 题解
1001 数长方形 题目大意 平面内有N条平行于坐标轴的线段,且不会在端点处相交 问共形成多少个矩形 算法思路 枚举4条线段的全部组合.分别作为矩形四条边.推断是否合法 时间复杂度: O(N4) 代码 ...
- Contest Round #451 (Div. 2)F/Problemset 898F Restoring the Expression
题意: 有一个a+b=c的等式,去掉两个符号,把三个数连在一起得到一个数 给出这个数,要求还原等式,length <= 1e6 三个数不能含有前导0,保证有解 解法: 铁头过题法,分类然后各种判 ...
- Codeforces Round #284 (Div. 2)A B C 模拟 数学
A. Watching a movie time limit per test 1 second memory limit per test 256 megabytes input standard ...
- Sending messages to non-windowed applications -- AllocateHWnd, DeallocateHWnd
http://delphi.about.com/od/windowsshellapi/l/aa093003a.htm Page 1: How Delphi dispatches messages in ...
- Codeforces 240 F. TorCoder
F. TorCoder time limit per test 3 seconds memory limit per test 256 megabytes input input.txt output ...
- cf499B-Lecture 【map】
http://codeforces.com/problemset/problem/499/B B. Lecture You have a new professor of graph theo ...
- Codeforces 240F. TorCoder 线段树
线段树统计和维护某一区间内的字母个数.. . . F. TorCoder time limit per test 3 seconds memory limit per test 256 megabyt ...
- 物联网学生科协第三届H-star现场编程比赛
问题 A: 剪纸片 时间限制: 1 Sec 内存限制: 128 MB 题目描写叙述 这是一道简单的题目,假如你身边有一张纸.一把剪刀.在H-star的比赛现场,你会这么做: 1. 将这张纸剪成两片(平 ...
- [cf contest 893(edu round 33)] F - Subtree Minimum Query
[cf contest 893(edu round 33)] F - Subtree Minimum Query time limit per test 6 seconds memory limit ...
- 水题 Codeforces Round #307 (Div. 2) A. GukiZ and Contest
题目传送门 /* 水题:开个结构体,rk记录排名,相同的值有相同的排名 */ #include <cstdio> #include <cstring> #include < ...
随机推荐
- Windows10(or windows11) Hyper-V 创建虚拟交换机后宿主机上传速度变特别慢的问题解决
问题 我在我的win11上启用了Hyper-v,装了个虚拟机跑了个CentOS7.6,为了让centos和宿主机通信在同个网段搞了个桥接网络,网络环境如下 然后我测试一个文件上传功能的时候发现网络上传 ...
- Mac修改文件名的颜色
文章目录 前言 文件类型 LSCOLORS介绍 颜色 如何设置LSCOLORS环境变量 前言 Mac中修改文件名颜色是通过LSCOLORS这个环境变量来控制的 文件类型 11种文件类型信息如下所示 序 ...
- 免费且离线的同声翻译利器「GitHub 热点速览」
开源的翻译软件众多,但大多数依赖于翻译 API 服务,因此就需要联网.有次数限制.并非完全免费.然后,本周上榜的是一款可以离线使用的 Android 翻译软件:RTranslator,它创建于 4 年 ...
- 了解Microsoft Media Foundation
关于Microsoft Media Foundation 是什么 Microsoft Media Foundation是用来处理(创建.修改.传输.合成)多媒体数据(音视频)的一个平台. 有什么用 M ...
- Linux 内核:sysfs 有关的API
背景 相关文章:1.sysfs与kobject基类 下面内容基本上参考(有删改):https://blog.csdn.net/qb_2008/article/details/6846412 API a ...
- 模拟用户登录-cookes
import requests url = 'https://www.xread8.com/user/login.json' headers = { 'User-Agent': 'Mozilla/5. ...
- jsp+servlet+mysql-----------批量删除
jsp: <div class="result-wrap"> <form action="${pageContext.request.contextPa ...
- Blazor Server App Cannot find the fallback endpoint specified by route values
github官方issues中提到的解决方案,CreateBuilder时指定项目绝对路径可以解决. 1 // 指定项目路径,也可以用Assembly.GetCallingAssembly获取 2 c ...
- C# 获取指定年月的第一天和最后一天、获取本月的第一天和最后一天、获取当前日期的星期几等
•获取指定年月的第一天 public static DateTime GetCurMonthFirstDay(string year,string mon) { DateTime AssemblDat ...
- 深入解析 Vue Router:构建单页面应用的利器
Vue.js 是一个渐进式 JavaScript 框架,常用于构建用户界面.随着应用的复杂度增加,路由(Routing)变得越来越重要,这就是 Vue Router 的用武之地.Vue Router ...