SMU Summer 2024 Contest Round 5
SMU Summer 2024 Contest Round 5
Robot Takahashi
思路
按照 \(W_i\) 排个序,算一下前缀后缀 1 和 0 的个数就行了。答案大概是一个 \(\max(ans,pre_i+suf_{i+1})\) 的形式。
排序之后当 \(W_i=W_{i+1}\) 时无法在 i,i+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;
string s;
cin >> s;
s = " " + s;
vector<array<int, 2>> w(n + 1);
for (int i = 1; i <= n; i ++) {
cin >> w[i][0];
w[i][1] = s[i] - '0';
}
sort(w.begin() + 1, w.end());
vector<int> pre(n + 1), suf(n + 2);
for (int i = 1; i <= n; i ++)
pre[i] = pre[i - 1] + (!w[i][1]);
for (int i = n; i >= 1; i --)
suf[i] = suf[i + 1] + w[i][1];
int ans = 0;
for (int i = 0; i <= n; i ++) {
if (w[i][0] != w[i + 1][0]) {
ans = max(ans, pre[i] + suf[i + 1]);
}
}
cout << ans << '\n';
return 0;
}
Connect 6
题意
有一个 \(N\times N\) 的棋盘网格用 \(N\) 行字符串 \(S_i\) 来表示。如果 \(S_{i,j}\) 是 #,说明棋盘的第 \(i\) 行第 \(j\) 列有一个棋子,否则如果 \(S_{i,j}\) 是 .,说明没有棋子。
请你判断是否可以再加入最多两个棋子使得棋盘存在六子连。六子连的定义是,存在某行、某列或者某对角线上有连续的六个棋子。
思路
暴力判断即可。
代码
#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<string> s(n);
for (auto &i : s)
cin >> i;
int ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i + 5 < n) { //列
int cnt = 0;
for (int k = i; k <= i + 5; k++)
cnt += s[k][j] == '.';
ans |= cnt <= 2;
}
if (j + 5 < n) { //行
int cnt = 0;
for (int k = j; k <= j + 5; k++)
cnt += s[i][k] == '.';
ans |= cnt <= 2;
}
if (i + 5 < n && j + 5 < n) { // 主对角线
int cnt = 0;
for (int k = 0; k <= 5; k++)
cnt += s[i + k][j + k] == '.';
ans |= cnt <= 2;
}
if (i - 5 >= 0 && j + 5 < n) { // 副对角线
int cnt = 0;
for (int k = 0; k <= 5; k++)
cnt += s[i - k][j + k] == '.';
ans |= cnt <= 2;
}
}
}
puts(ans ? "Yes" : "No");
return 0;
}
Strange Balls
题意
高桥君收到了 \(N\) 个奇怪的球,球摆成一列,每个球的表面都写着一个数字,第 \(i\) 个球的表面数字是 \(a_i\)。
高桥君准备将所有的球从 \(1\) 到 \(N\) 依次放入桶中。桶是圆柱形的,底面是封死的,只能从圆柱形顶端放入。桶比较窄,桶中的球只能全部竖着叠放。
高桥君在放球的过程中,奇怪的事情发生了,如果桶中有连续 \(x\) 个值为 \(x\) 的球,这些球将会消失。
请你帮助高桥君计算出,从 \(1\) 到 \(N\) 依次放入每个球后,桶中的球有多少个?
思路
用栈记录每次放入的元素,cnt 数组记录栈中栈顶值连续相同的个数,当栈顶值连续个数与值相同时,从栈中弹出相应个数即可。
代码
#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<int> a(n + 1);
for (int i = 1; i <= n; i ++)
cin >> a[i];
vector<int> st, cnt(n + 1);
for (int i = 1; i <= n; i ++) {
int siz = st.size();
if (siz && a[i] == st.back())
cnt[siz] = cnt[siz - 1] + 1;
else
cnt[siz] = 1;
st.push_back(a[i]);
if (cnt[siz] == a[i]) {
int k = a[i];
while (k--)
st.pop_back();
}
cout << st.size() << '\n';
}
return 0;
}
Linear Probing
题意
维护一个长度为 \(2^{20}\) 的,下标从 \(0\) 到 \(2^{20}-1\) 的数列 \(a\)。初始时,数列中的每一项均为 \(-1\)。令 \(n=2^{20}\)。
给定 \(q\) 次操作,每次操作内容如下:
1 x:将变量 \(h\) 的值定为 \(x\)。将 \(h\) 不断加 \(1\) 直到 \(a_{h \bmod n} = -1\) 为止。令 \(a_{h \bmod n}\) 的值为 \(x\)。2 x:输出 \(a_{x \bmod n}\) 的值。
思路
考虑并查集思想。
首先所有的节点父亲都是自己,一旦自己被修改了,那就让自己的父亲指向右边第一个不为 -1 的节点,注意取模与开 longlong,还有路径压缩。
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
const int N = 1 << 20;
vector<i64> fa(N), a(N, -1);
iota(fa.begin(), fa.end(), 0);
auto find = [&](auto & self, int x)->int{
return fa[x] == x ? x : fa[x] = self(self, fa[x]);
};
int q;
cin >> q;
while (q --) {
i64 op, x;
cin >> op >> x;
if (op == 1) {
int y = find(find, x % N);
a[y] = x;
fa[y] = find(find, (y + 1) % N);
} else {
cout << a[x % N] << '\n';
}
}
return 0;
}
Red Polyomino
题意
给你边长为 N 的且仅由字符 # 和 . 组成的正方形阵列,其中 # 表示黑色格子, . 表示白色格子。你需要在白色格子中选择 K 个涂成红色,且使红色格子互相连接(仅包括上下左右相邻),求有多少种可能的方案。
思路
从 \(N\times N\) 的矩阵中选择 \(K\) 个,最多有 \(C_{64}^8\) 种,考虑暴力。
暴力需要一点技巧,常规暴力是从红色方块向四周搜索,但这样会因为枚举的方向而使答案一直不对,需要反过来想通过 n 方遍历地图从空白格子向四周找红色方块。
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
vector<string> s(n);
for (auto &i : s) cin >> i;
int ans = 0;
const int u[] = {1, -1, 0, 0};
const int v[] = {0, 0, 1, -1};
auto solve = [&](auto & self, int num) {
if (num == k) {
ans ++;
return ;
}
vector<pair<int, int>> loc;
for (int l = 0; l < n; l ++)
for (int c = 0; c < n; c++) {
for (int i = 0; i < 4; i ++) {
if (s[l][c] == '.') {
int dx = l + u[i];
int dy = c + v[i];
if (dx >= 0 && dx < n && dy >= 0 && dy < n && s[dx][dy] == 'r' ) {
s[l][c] = 'r';
self(self, num + 1);
s[l][c] = '#';
loc.push_back({l, c});
}
}
}
}
for (auto [x, y] : loc)
s[x][y] = '.';
};
for (int i = 0; i < n; i ++) {
for (int j = 0; j < n; j ++) {
if (s[i][j] == '.') {
s[i][j] = 'r';
solve(solve, 1);
s[i][j] = '#';
}
}
}
cout << ans << '\n';
return 0;
}
Stronger Takahashi
题意
有一个城镇被划分为H行和W列的单元格网格。
如果 \(S_i,_j\) 是' . ',则为道路;如果 \(S_i,_j\) 为' # ',则为障碍物。
高桥将从家里去鱼市。他的房子在左上角的方格,鱼市在右下角的方格。
高桥可以从一个单元格向上、向下、向左或向右移动到可通过的单元格。他不能离开小镇,也不能进入街区。
但是,他可以一次摧毁一个 2$\times$2 正方形区域中的所有障碍物,使这个区域可以通过,但需要消耗一点能量。
找到高桥进入鱼市需要消耗的最少能量。
思路
不使用能量时,转移消耗为 0 ,使用能量时,消耗 1 能量,则为典型的 01 bfs,使用双端队列跑 bfs 即可。
代码
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
int dx1[4][2] = {{0, -1}, { -1, 0}, {1, 0}, {0, 1}};
int dx2[25][2] = {{ -1, -1}, {1, 1}, { -1, 1}, {1, -1},
{2, -1}, {2, 1}, {1, 2}, {1, -2}, { -2, 1}, { -2, -1},
{ -1, -2}, { -1, 2}, {2, 0}, {0, 2}, { -2, 0}, {0, -2}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<string> s(n);
for (auto &i : s)
cin >> i;
vector dis(n, vector<i64>(m, INT_MAX));
deque<array<int, 2>> Q;
Q.push_front({0, 0});
dis[0][0] = 0;
while (Q.size()) {
auto [x, y] = Q.front();
Q.pop_front();
for (int i = 0; i < 4; i ++) {
int dx = x + dx1[i][0], dy = y + dx1[i][1];
if (dx >= 0 && dx < n && dy >= 0 && dy < m && s[dx][dy] == '.') {
if (dis[dx][dy] > dis[x][y]) {
dis[dx][dy] = dis[x][y];
Q.push_front({dx, dy});
}
}
}
for (int i = 0; i < 16; i ++) {
int dx = x + dx2[i][0], dy = y + dx2[i][1];
if (dx >= 0 && dx < n && dy >= 0 && dy < m) {
if (dis[dx][dy] > dis[x][y] + 1) {
dis[dx][dy] = dis[x][y] + 1;
Q.push_back({dx, dy});
}
}
}
}
cout << dis[n - 1][m - 1] << '\n';
return 0;
}
Predilection
题意
有一个长度为 N 的数列 A。
你可以进行若干次,最多 N−1 次操作,选择相邻的两个数,删去他们,并在原位置放上他们两个的和。
现在你需要求出可能产生的序列个数。
思路
考虑 dp。
考虑对这个数组进行前缀和操作,用 \(num_i\) 表示第 个数,则 \(_=∑_{=1}^_\)。我们发现合并第 和 +1 个数合并就是第 和 +1 个数后进行前缀和操作,实际上就是删除了 \(_\)。对于合并第 和 +1 个数的操作, 最多取到 −1,即 < ,从中得出在删除操作中,\(_\) 必须保留。因为每个前缀和只能对应一个数,于是题意简化成:对给出的 个数进行前缀和操作,每次可以删除任意一个 \(_(<)\),求共有多少种不同的序列。可以发现,实际上就是求前缀和数组 \(_1∼_{−1}\) 的不同子序列的个数。
若此数之前出现过,\(dp_=dp_{−1}\times 2−dp_{-1}\) 这里是因为我们若接上上一个出现过的所有东西都会和上一个接上重复。
否则,\(dp_=dp_{−1}×2+1\) 这里先接上前面的所有在加上自己。
最后输出 \(dp_{n-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;
cin >> n;
const int mod = 998244353;
vector<i64> a(n + 1);
for (int i = 1; i <= n; i ++) {
cin >> a[i];
a[i] += a[i - 1];
}
map<i64, int> mp;
vector<i64> dp(n + 1);
dp[1] = 1, mp[a[1]] = 1;
for (int i = 2; i <= n; i ++) {
int last = mp[a[i]];
if (!last) dp[i] = (dp[i - 1] * 2 + 1) % mod;
else dp[i] = (dp[i - 1] * 2 % mod - dp[last - 1] + mod) % mod;
mp[a[i]] = i;
}
cout << dp[n - 1] + 1 << '\n';
return 0;
}
SMU Summer 2024 Contest Round 5的更多相关文章
- 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 < ...
随机推荐
- java并发的发布和订阅测试
现在编码的时候,为了处理消息,大家动不动就上个重器,例如MQ之类的.但很多时候,并不是那么有必要,因为数据量和并发其实远远不够. 可以替代的方案非常多,其中一个是java.util.concurren ...
- (Java)常用类库
Spring 常用工具类 Spring作为常用的开发框架,在Spring框架应用中,排在ApacheCommon.Guava.Huool等通用库后,第二优先级可以考虑使用Spring-core-xxx ...
- ubuntu16 python2 安装M2Crypto报错
正文 pip2 install M2Crypto # 报错: # unable to execute 'swig': No such file or directory # error: comman ...
- VS2015 、VS2017 MFC输出日志到控制台窗口
原来使用VS2010建立的项目,安装VS2017后,发现MFC无法通过调试窗口输出printf打印的内容,在CSDN上找到了一个解决方案,使用后恢复打印调试信息功能,推荐如下: https://blo ...
- koa web框架入门
1.在hello-koa这个目录下创建一个package.json,这个文件描述了我们的hello-koa工程会用到哪些包.完整的文件内容如下: { "name": "h ...
- CF620E
题目 CF620E 思路 这个题是一个在树上操作的题,每次操作的对象都是以一个结点为根的子树,在1e5的操作下暴力做法必然会超时 观察到c的范围很小,可以考虑状态压缩 考虑将此问题转化为区间问题,利用 ...
- PHP 缓存技术
PHP 缓存介绍 什么是缓存 数据交换的缓冲区(称作Cache) 临时文件交换区 缓存作用 减少网络延迟,加快页面打开速度 减少数据查询次数,降低数据库压力 降低系统负荷,极大的提升系统性能 常用缓存 ...
- oeasy教您玩转vim - 22 - 配置文件
配置文件 回忆上节课内容 我们上次了解到了状态横条 通过转义表示 item 控制 item 宽度的方法 将 item 成组的方法 还有一个总开关 laststatus 但是每次都要写很长的一段话来配置 ...
- [oeasy]教您玩转python - 0005- 勇闯地下城
继续运行 回忆上次内容 上次从1行代码进化到了2行代码 yy p粘贴剪贴板中的内容 将剪贴板中的代码粘贴9999次 9999p 真的实现了万行代码梦 是真·圆梦 没有撒谎的那种 不过圆梦之后多少 ...
- php执行出现权限问题