USACO 2021 Contest 1 Bronze 题解
蒟蒻第一次打 USACO,只打了 Bronze 就跑路了。不得不说也有很有意思的题目。接下来就看看题目吧。
由于现在还看不到题目,只给出加工后的题目大意。
T1 Lonely Photo
Content
有一个长度为 \(n\) 的字符串 \(s\),仅包含两种字符:G 和 H。定义字符串 \(s'\) 是孤独的,当其仅当 \(s'\) 中恰好只有一个 G 或 H 且 \(|s'|\geqslant 3\)。例如,字符串 GHGGG、GHHHH 是孤独的,而字符串 GH、GHGHG 不是。现在,请你求出 \(s\) 的所有孤独的子串的个数。
数据范围:\(n\leqslant 5\times 10^5\)。
Solution
我们很容易想到一个 \(\mathcal O(n^2)\) 的做法,即暴力模拟每个子串并判断其是否是孤独的。但是有没有更优的方法?确实有。我们可以先预处理出当前字符前面、后面有多少个连续的与当前字符不同的字符,设在 \(i\) 位置上的字符前面连续的与当前字符不同的字符有 \(\textit{bef}_i\) 个,后面连续的与当前字符不同的字符有 \(\textit{aft}_i\) 个。那么,我们就可以对于每个位置直接算其对答案的贡献就好了。具体地,对于当前位置 \(i\):
- 如果 \(\textit{bef}_i>0\) 且 \(\textit{aft}_i>0\),那么当前位置对答案的贡献加上 \(\textit{bef}_i\cdot\textit{aft}_i\)。
- 如果 \(\textit{bef}_i>1\),那么那么当前位置对答案的贡献加上 \(\textit{bef}_i-1\)。
- 如果 \(\textit{aft}_i>1\),那么那么当前位置对答案的贡献加上 \(\textit{aft}_i-1\)。
综上,当前位置 \(i\) 对答案的贡献是 \(\textit{bef}_i\cdot\textit{aft}_i+\max(0,\textit{bef}_i-1)+\max(0,\textit{aft}_i-1)\)。
由此,我们将算法优化到了 \(\mathcal{O}(n)\),就可以通过这道题目了。
Code
赛时代码。
namespace Solution {
const int N = 5e5 + 7;
int n, cntg, cnth, g[N], h[N], numg[N], numh[N], bef[N], aft[N];
char a[N];
iv Sub1_work() {
ll ans = 0;
F(int, i, 1, n) {
if(i <= n - 2 && ((a[i] == 'G' && a[i + 1] == 'H' && a[i + 2] == 'H') || (a[i] == 'H' && a[i + 1] == 'G' && a[i + 2] == 'G'))) {
int cur = i + 2;
for(; cur < n && a[cur + 1] == a[i + 2]; cur++);
ans += (cur - (i + 2) + 1);
}
if(i > 1 && i < n && ((a[i] == 'G' && a[i - 1] == 'H' && a[i + 1] == 'H') || (a[i] == 'H' && a[i - 1] == 'G' && a[i + 1] == 'G'))) {
int curl = i - 1, curr = i + 1;
for(; curl > 1 && a[curl - 1] == a[i - 1]; curl--);
for(; curr < n && a[curr + 1] == a[i + 1]; curr++);
ans += 1ll * ((i - 1) - curl + 1) * (curr - (i + 1) + 1);
}
if(i >= 3 && ((a[i] == 'G' && a[i - 1] == 'H' && a[i - 2] == 'H') || (a[i] == 'H' && a[i - 1] == 'G' && a[i - 2] == 'G'))) {
int cur = i - 2;
for(; cur > 1 && a[cur - 1] == a[i - 2]; cur--);
ans += ((i - 2) - cur + 1);
}
}
write(ans);
}
iv Sub2_work() {
F(int, i, 1, n) if(a[i] == 'G') g[++cntg] = i, numg[i] = cntg;
F(int, i, 1, n) if(a[i] == 'H') h[++cnth] = i, numh[i] = cnth;
int cnt = 0;
F(int, i, 1, n) {
if(a[i] == 'G') cnt++;
else {
bef[i] = cnt;
if(numh[i] != 1) aft[h[numh[i] - 1]] = cnt;
cnt = 0;
}
}
aft[h[cnth]] = cnt, cnt = 0;
F(int, i, 1, n) {
if(a[i] == 'H') cnt++;
else {
bef[i] = cnt;
if(numg[i] != 1) aft[g[numg[i] - 1]] = cnt;
cnt = 0;
}
}
aft[g[cntg]] = cnt;
ll ans = 0;
F(int, i, 1, n) {
ans += 1ll * bef[i] * aft[i];
if(bef[i] >= 2) ans += bef[i] - 1;
if(aft[i] >= 2) ans += aft[i] - 1;
}
write(ans);
}
iv Main() {
read(n), scanf("%s", a + 1);
if(n <= 5000) Sub1_work();
else Sub2_work();
return;
}
}
T2 Air Cownditioning
Content
有两个长度为 \(n\) 的数组 \(a,b\)。每次操作你可以选择一个区间 \([l,r]\),然后将下标在这个区间里面的所有 \(b_i\) 加 \(1\) 或者减 \(1\),求最少需要多少操作才能够使得 \(\forall i\in[1,n],a_i=b_i\)。
数据范围:\(1\leqslant n\leqslant 10^5\)。
Solution
首先我们令 \(c_i=a_i-b_i\),然后就把这道题目转换成了最少需要多少次操作使得 \(\forall i\in[1,n],c_i=0\)。然后我们就发现有一道经典的差分题目和这题非常相像,就是洛谷 P4552。没做那道题目的同学可以先去做做那道题目,然后你就发现这道题目可以随便乱杀了。
我们可以套路地将 \(c_i\) 进行一个差分操作,即令 \(d_i=c_i-c_{i-1}\),然后就又转化为最少需要多少操作才能够使得 \(\forall i\in[1,n],d_i=0\)。然后,我们可以统计一下所有 \(d_i\) 中正数的和 \(sum_1\) 和负数的和的绝对值 \(sum_2\),为什么呢?首先我们想想对 \([l,r]\) 进行一次操作之后会对差分数组 \(d\) 有什么影响。分析之后不难发现:
- 如果操作为全加 \(1\),那么 \(d_{l-1}\leftarrow d_{l-1}+1\),\(d_r\leftarrow d_r-1\)。
- 如果操作为全减 \(1\),那么 \(d_{l-1}\leftarrow d_{l-1}-1\),\(d_r\leftarrow d_r+1\)。
然后再分析怎么让所有 \(d_i=0\),不难发现,我们首先选择 \(d_2,d_3,\dots,d_{n-1}\) 当中的一个正数和一个负数进行若干次操作,等不能执行这种操作之后,再拿一个正数和 \(d_n\) 进行操作,或者再拿一个负数和 \(d_1\) 进行操作(因为由定义可知,\(d_1>0\),\(d_n<0\))。然后你就可以发现这样的操作次数为 \(\min(sum_1,sum_2)+|sum_1-sum_2|=\max(sum_1,sum_2)\)。
于是这道题目就做完了,还弄了个双倍经验,简直美汁汁。
Code
赛时代码。
namespace Solution {
const int N = 1e5 + 7;
int n, cur, p[N], cf[N];
iv Main() {
read(n); F(int, i, 1, n) read(p[i]);
F(int, i, 1, n) read(cur), p[i] = p[i] - cur;
F(int, i, 1, n) cf[i] = p[i] - p[i - 1];
ll sum1 = 0, sum2 = 0;
F(int, i, 1, n) if(cf[i] > 0) sum1 += cf[i]; else sum2 += -cf[i];
write(max(sum1, sum2));
return;
}
}
T3 Walking Home
Content
\(T\) 组询问,每组询问给定一个大小为 \(n\times n\) 的地图,仅包含空地(用 . 表示)和障碍(用 H 表示),求在转弯不超过 \(k\) 次的情况下从 \((1,1)\) 到 \((n,n)\) 有多少种路线。
数据范围:\(2\leqslant n\leqslant 50\),\(1\leqslant k\leqslant 3\)。
Solution
你想着通过暴力 dfs 过这道题目,然而你发现最终 T 了两个点。然后你就想着用 dp 来解决了。
我们设 \(dp_{x,y,i,j}\) 表示从 \((1,1)\) 到 \((x,y)\),\(i=0/1/2\) 分别表示朝向为下/右/移动开始,转弯了 \(j\) 次的路线数。另令 \(dx_0=1\),\(dx_1=0\),\(dy_0=0\),\(dy_0=1\) 方便后面的转移。然后分两种情况讨论:
- 不转弯,则 \(dp_{x+dx_i,y+dy_i,i,j}\leftarrow dp_{x+dx_i,y+dy_i,i,j}+dp_{x,y,i,j}\),特别地,如果 \(x=1,y=1\),不要忘记加上 \(dp_{1,1,2,0}\)。
- 转弯,只能够在 \((x,y)\neq(1,1)\) 时进行,此时 \(dp_{x+dx_i,y+dy_i,i,j+1}\leftarrow dp_{x+dx_i,y+dy_i,i,j+1}+dp_{x,y,1-i,j}\)。
初始化为 \(dp_{1,1,2,0}=1\),答案即为 \(\sum\limits_{i=0}^1\sum\limits_{j=1}^k dp_{n,n,i,j}\)。
Code
赛时代码。
namespace Solution {
const int dx[2] = {1, 0};
const int dy[2] = {0, 1};
const int N = 57;
int n, k, ans, dp[N][N][3][7];
char a[N][N];
iv Main() {
MT {
read(n, k), memset(dp, 0, sizeof(dp)), ans = 0;
F(int, i, 1, n) scanf("%s", a[i] + 1);
dp[1][1][2][0] = 1;
F(int, i, 1, n) F(int, j, 1, n) if(a[i][j] != 'H') F(int, l, 0, 1) {
int x = i + dx[l], y = j + dy[l];
if(x < 1 || x > n || y < 1 || y > n || a[x][y] == 'H') continue;
F(int, t, 0, k) {
dp[x][y][l][t] += dp[i][j][l][t];
if(i == 1 && j == 1 && t == 0) dp[x][y][l][t] += dp[1][1][2][0];
}
if(i != 1 || j != 1) F(int, t, 0, k - 1) dp[x][y][l][t + 1] += dp[i][j][1 - l][t];
}
int ans = 0;
F(int, i, 0, 1) F(int, j, 1, k) ans += dp[n][n][i][j];
println(ans);
}
return;
}
}
USACO 2021 Contest 1 Bronze 题解的更多相关文章
- KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解
KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解 哦淦我已经菜到被ABC吊打了. A - Century 首先把当前年 ...
- 2018 ACM-ICPC Asia Beijing Regional Contest (部分题解)
摘要 本文主要给出了2018 ACM-ICPC Asia Beijing Regional Contest的部分题解,意即熟悉区域赛题型,保持比赛感觉. Jin Yong’s Wukong Ranki ...
- 2014-2015 ACM-ICPC, Asia Xian Regional Contest(部分题解)
摘要 本文主要给出了2014-2015 ACM-ICPC, Asia Xian Regional Contest的部分题解,说明了每题的题意.解题思路和代码实现,意即熟悉区域赛比赛题型. Built ...
- Comet OJ - Contest #2 简要题解
Comet OJ - Contest #2 简要题解 cometoj A 模拟,复杂度是对数级的. code B 易知\(p\in[l,r]\),且最终的利润关于\(p\)的表达式为\(\frac{( ...
- Comet OJ - Contest #2简要题解
Comet OJ - Contest #2简要题解 前言: 我没有小裙子,我太菜了. A 因自过去而至的残响起舞 https://www.cometoj.com/contest/37/problem/ ...
- 300iq Contest 1 简要题解
300iq Contest 1 简要题解 咕咕咕 codeforces A. Angle Beats description 有一张\(n\times m\)的方阵,每个位置上标有*,+,.中的一种. ...
- USACO January Contest Gold Time is Mooney 题解
题意 给出一个有向图,走到每个节点有 \(m_i\) 的收益,每一条边要走一天,走 \(T\) 天的花费是 \(C\cdot T^2\),求从节点 \(1\) 开始并且在节点 \(1\) 结束的旅行的 ...
- USACO 2013 November Contest Gold 简要题解
Problem 1. Empty Stalls 扫两遍即可. Problem 2. Line of Sight 我们发现能互相看见的一对点一定能同时看见粮仓的某一段.于是转换成有n段线段,问有多少对线 ...
- USACO section 1.1 C++题解
USACO section1.1:DONE 2017.03.03 TEXT Submitting Solutions DONE 2017.03.04 PROB Your Ride Is Here [A ...
随机推荐
- 国内首家!腾讯云正式成为 FinOps 基金会顶级会员
11月24日,腾讯云正式宣布加入FinOps基金会,作为国内首家FinOps基金会顶级会员,腾讯云将联合FinOps基金会,全面推进对FinOps标准和最佳实践的贡献,为企业提供云财务管理的最佳解决方 ...
- Linux排序数据
1.sort 默认是按照字符大小来排序,如果要按照数字大小排序,需要加参数-n,-M按月排序 如:sort text.txt按字符大小排序 sort -n text.txt 按照数字大小排序 sort ...
- Docker容器基础入门认知-网络篇
这篇文章中,会从 docker 中的单机中的 netns 到 veth,再到单机多个容器之间的 bridge 网络交互,最后到跨主机容器之间的 nat 和 vxlan 通信过程,让大家对 docker ...
- Go IF 条件语句
条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true 来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句. 以下是在大多数编程语言中发现的典型条件语句的一般形式 ...
- 题解 P5320 - [BJOI2019]勘破神机(推式子+第一类斯特林数)
洛谷题面传送门 神仙题(为什么就没能自己想出来呢/zk/zk) 这是我 AC 的第 \(2\times 10^3\) 道题哦 首先考虑 \(m=2\) 的情况,我们首先可以想到一个非常 trivial ...
- ACAM 题乱做
之前做了不少 ACAM,不过没怎么整理起来,还是有点可惜的. 打 * 的是推荐一做的题目. I. *CF1437G Death DBMS 见 我的题解. II. *CF1202E You Are Gi ...
- P7708「Wdsr-2.7」八云蓝自动机 Ⅰ
*X. P7708「Wdsr-2.7」八云蓝自动机 Ⅰ. 摘自 分治与根号数据结构学习笔记 第三部分 莫队 例题 X.. 一道莫队好题.私以为本题最有价值的地方在于对单点修改的转化以及对交换两个数的处 ...
- Docker Nginx-Proxy 容器Nginx Proxy反向代理
Docker Nginx-Proxy 容器Nginx Proxy反向代理 简单介绍 Docker容器的自动Nginx反向代理 dockerhub地址 https://hub.docker.co ...
- Ansi,UTF8,Unicode,ASCII编码的区别
Ansi,UTF8,Unicode,ASCII编码的区别 近日需要不同的编码,关于上述编码,一直迷迷糊糊,查了些资料,总算大致了解了, 下面全是从网上搜来的: 1. ASCII和Ansi编码 ...
- day06 HTTP协议
day06 HTTP协议 HTTP协议 什么是http? HTTP 全称:Hyper Text Transfer Protocol 中文名:超文本传输协议 是一种按照URL指示,将超文本文档从一台主机 ...