C题:题目给了一个整数数组a与字符串数组s,然后说s数组用来匹配a数组,即s[i]='>',那么a[i]必须大于0.而s有'>','<','Z'三种字符,分别代表三种意思.但现在的a数组并不匹配s数组,因此要我们改动a数组以满足题意,这就是我们要解决的.看样例那么就来到了本题的"诈骗点",按照题意,后一种的状态受前一种决定,那么应该是dp,实际上这也能dp来做,但这将把问题复杂化,我们只需要先遍历s的>,<字符,将对应的a修改一致,再对s的Z字符遍历,对不符合的再修改,这样既符合了前面的s,也符合了现在的s,也就是说前面的是<,那么我要把a对应的变为负数,后面的是Z,我只需要也改成负数就行了,否则将要多改一次,而且前面的<是不能动的.这就是贪心的思想.(当时没有考虑到Z字符的特殊性,只是遍历S修改次数,这应该是多数人一开始的想法,然后很多人wa了之后会考虑dp的方案,即思路错误了).

具体操作详见代码(记得开i64,有乘法):

using namespace std;
using i64 = long long;

void solve() {
	int n;
	cin >> n;
	vector<i64>a(n);
	string s;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	cin >> s;
	i64 ans = 0;
	for (int i = 0; i < n; i++) {
		if (s[i] == '>') {
			if (a[i] <= 0) {
				a[i] = 1;
				ans++;
			}
		} else if (s[i] == '<') {
			if (a[i] >= 0) {
				a[i] = -1;
				ans++;
			}
		}
	}
	for (int i = 0; i < n; i++) {
		if (s[i] == 'Z') {
			if (a[i]*a[i - 1] <= 0) {
				a[i] = a[i - 1];
				ans++;
			}
		}
	}
	cout << ans << endl;
}


int main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int t = 1;
	cin >> t;
	while (t--) {
		solve();
	}
	return 0;
}

D题:给出长度为n的数组,数组有正有负,要求使得数组总和最大.题目又给了两个操作,第一个操作选择两个数删去,第二个操作选择三个数删去.若想数组总和最大,应该通过操作尽可能地将负数删去.通过样例,我们可以通过操作将连续的负数删去,最后剩下若干个单个负数或者是没有负数,但很遗憾这正是出题人设下的诈骗点,诈骗我们去贪过去,事实是根本贪不了(不过作者想到了一个貌似能贪过去的solution,但代码及其丑且冗长,细看代码其实还是用了dp因此题解即最优解).这是一道很经典的线性dp,根据题目条件有三种决策:1.不删数字.2删两个数字.3删三个数字.分别代表状态转移方程:dp[i]=dp[i-2],dp[i]=dpi-3,然后on遍历数组取最优情况即可.代码如下:

using namespace std;
using i64 = long long;

void solve() {
	int n;
	cin >> n;
	vector<i64> dp(n + 1);
	dp[0] = 0;
	for (int i = 1; i <= n; i++) {
		int x;
		cin >> x;
		dp[i] += dp[i - 1] + x;
		if (i >= 2) {
			dp[i] = max(dp[i], dp[i - 2]);
		}
		if (i >= 3) {
			dp[i] = max(dp[i], dp[i - 3]);
		}
	}
	cout << dp[n] << endl;
}


int main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int t = 1;
	cin >> t;
	while (t--) {
		solve();
	}
	return 0;
}