可达鸭CSP-j复赛模拟赛韩润琦补题报告day4

一、题目报告

                                                   赛时爆零(因为文件名写错了 ̄へ ̄)

二、赛中概况

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;
}

总结:
(1)下次别再写错文件名了!!!!!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值