一、题目报告
赛时爆零(因为文件名写错了 ̄へ ̄)
二、赛中概况
T1做题过程:T1这道题目,我大眼一看,发现它的题目并不是很难,我就开始搞这道题。后来,我发现有一个题目的条件我写不出来,我便看了一下数据范围,它有30%的数据没有这个条件,我便放弃了那个写不出来的条件。但是,那个我会的条件我也没做出来。所以,就算没有写错文件名,这道题也会爆零。看一下这个奇怪的for循环。
for(int i = 1; i <= n; i++) {
if(c[i] >= '0' && c[i] <= '9') {
if(c[i + 1] >= '0' && c[i + 1] <= '9') {
a[++cnt1] = (c[i] - 48) * 10 + (c[i + 1] - 48);
x = c[i + 1];
} else {
a[++cnt1] = c[i];
a[cnt1] -= 48;
if (x == c[i]) {
continue;
}
x = 0;
}
}
T2做题过程:这道题目因为T1耗费的时间太长,只是根据表面意思,写了一个很简单的代码(这道题目需要改变队列的顺序,求一个最小值,但我没有找最小值,求差之后,直接输出了),我以为可以混个10分20分的,但是题目没有给我机会,它爆零了。这到题目完全是无脑写的。
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int n,a[N];
int sum1 = 0, sum2 = 0;
int main(){
freopen("spearshield.in","r", stdin);
freopen("spearshield.out", "w", stdout);
cin >> n;
for(int i = 1; i <= n; i++){
cin >> a[i];
if(a[i] == 0){
sum1 += i;
}else{
sum2 += i;
}
}
cout << sum1 - sum2;
fclose(stdin);
fclose(stdout);
return 0;
}
T3T4做题过程:你懂的,没时间了........
三、解题报告
T1.
题目大意:原题废话比较多,我来总结一下吧:就是现在给定一个长度为 n 的仅包含小写字母和数字的字符串,字母表示需要复读的消息,数字表示要复读的次数。然而复读没有这么简单,小可想进行一个更复杂的复读模拟, 于是这个字符串中可能包含多个数字, 当多次出现数字时,例如 a5b2,我们从左到右解析这个字符串,5a 表示将 a 复读 5 遍,即原字符串变 为 aaaaab ,然后遇到数字 2 ,再将所有消息全部复读 2 遍,即 aaaaabaaaaab 。
题目解析:在读懂题目后,主要考察模拟能力。
对于30分以内:只考虑个位数,少了一层while循环。
对于100分:
要注意的是:
①每次重复是当前数字之前的所有字符,而不是只重复单个字符或部分字符。
可以开一个答案字符串,在每次出现数字的时候,每次都后面拼接本身,当然拼接前需要保存一下自己,然后每次都拼接保存的本身。
②数字在字符串中出现,需要拼成 int类型的,而且数字不一定是个位数。
代码中有注释
正解代码:
接下来奉上正解代码
#include<bits/stdc++.h>
using namespace std;
int t, n, tmp, pos;
string a, ans, c;
int main() {
cin >> t;
while (t--) {
cin >> n >> a;
a = " "+ a, ans ="";//a串下标可以从1~n,也可以前面不加空格,从0~n-1
for (int i = 1; i <= n; ++i) {
if (a[i] >= 'a' && a[i] <= 'z') ans += a[i]; //答案字符串正常拼接
else {
tmp = 0, pos = i; //找到数字是tmp位
while (a[pos] >= '0' && a[pos] <= '9') {
tmp *= 10;
tmp += a[pos] - '0';
pos++;
}
i = pos - 1; //需要先退到最后一个数字字符,因为外层for会增加到第一个非数字字符
c = ans, tmp--; //本身算一遍
while (tmp--)ans += c; //拼接tmp次前面的ans字符串
}
}
cout << ans << endl;
}
return 0;
}
T2
题目大意:
题目解析:
思路:
对于50分:可以双层循环,先找断点,然后前半段累加攻击和,前半段累加防御和。时间复杂度为O(n^2);
对100分:
思路1: 前缀和
枚举所有断点,然后求绝对值。但是10^5 会时间超限。
所以可以提前打表求某一段的攻击力、某一段的防御力。用前缀和。时间复杂度 O(n).
思路2:递推
假设一开始分界线在位置 0(即所有人都在第二阵营),然后逐渐移动分界线,维护双方战斗力的变化。
需要提前打表,把字符串中的字符对应成能力(攻击or防御)存储。
正解代码
接下来奉上正解代码(1)
#include<iostream>
#include<string>
#include<cstdio>
#include<cmath>
using namespace std;
const long long N = 1e5 + 10;
const int INF = 0x7fffffff;
long long n;
string s;
long long xx = 0, yy = 0;
long long sum1[N], sum2[N];
int main(){
scanf("%lld", &n);
cin >> s;
s = ' ' + s;
for(long long i = 1; i <= s.length(); i++){
sum1[i] = sum1[i - 1];
sum2[i] = sum2[i - 1];
if(s[i] == '0'){
sum1[i] = sum1[i - 1] + i;
}else{
sum2[i] = sum2[i - 1] + i;
}
}
long long minn = INF;
for(long long i = 0; i <= n + 1; i++){
xx = 0, yy = 0;
xx = sum1[i] - sum1[0];
yy = sum2[n] - sum2[i];
if(abs(xx - yy) < minn){
minn = abs(xx - yy);
}
}
printf("%lld", minn);
return 0;
}
(2)
T3.
题目大意:这是一道stj题目,
题目解析:
正解代码
接下来奉上正解代码
#include<bits/stdc++.h>
using namespace std;
int T, n, m;
string str[100000], tgt;
int main() {
cin >> T;
while (T--) {
cin >> m;
for (int i = 1; i <= m; i++)
cin >> str[i];
cin >> tgt;
n = tgt.length();
tgt = ' ' + tgt;
for (int i = 1; i <= n; i++) { //找哪个[i]可以改
for (int j = 1; j <= m; j++) {
if (i < str[j].length()){
continue;
}
if (tgt.substr(i - str[j].length() + 1, str[j].length()) == str[j]) {
//以[i]为结尾的单词
tgt[i] = '*';
}
}
}
for (int i = 1; i <= n; i++)
cout << tgt[i];
cout << endl;
}
return 0;
}
T4.
题目大意:
题目解析:
正解代码
接下来奉上正解代码
#include<bits/stdc++.h>
using namespace std;
const int p = 1e9 + 7;
struct node {
int to, nxt;
};
int cnt, head[1000005], d[1000005];
long long a[1000010], up[1000010], down[1000010];
node e[5000005];
vector<pair<int, int> > g;
void add(int u, int v) {
e[++cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
void dfs(int u, int fa) {
g.push_back(make_pair(d[u], u));
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v == fa) {
continue;
}
d[v] = d[u] + 1;
dfs(v, u);
}
}
int main() {
int n, m, q;
cin >> n >> m >> q;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n - 1; i++) {
int u, v;
cin >> u >> v;
add(u, v);
add(v, u);
}
dfs(1, 1);
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
add(u, v);
add(v, u);
}
for (int i = 1; i <= q; i++) {
int t, u, v;
cin >> t >> u >> v;
if (t == 1) {
up[u] = (up[u] + v) % p;
} else {
down[u] = (down[u] + v) % p;
}
}
sort(g.begin(), g.end());
for (int i = 0; i < g.size(); i++) {
int x = g[i].second;
for (int j = head[x]; j; j = e[j].nxt) {
int y = e[j].to;
if (d[y] > d[x]) {
down[y] = (down[y] + down[x]) % p;
}
}
}
reverse(g.begin(), g.end());
for (int i = 0; i < g.size(); i++) {
int x = g[i].second;
for (int j = head[x]; j; j = e[j].nxt) {
int y = e[j].to;
if (d[y] < d[x]) {
up[y] = (up[y] + up[x]) % p;
}
}
}
for (int i = 1; i <= n; i++) {
cout << (a[i] + up[i] + down[i]) % p << ' ';
}
return 0;
}