牛客周赛 Round 87


A. 小苯的V图

点击查看代码
void solve() {
    int x, y, z;
    std::cin >> x >> y >> z;
    if (y < x && y < z) {
    	std::cout << "YES\n";
    } else {
    	std::cout << "NO\n";
    }
}

B. 小苯的数字切割

枚举分隔位置

点击查看代码
void solve() {
	std::string s;
	std::cin >> s;
	int ans = 0;
	for (int i = 1; i < s.size(); ++ i) {
		ans = std::max(ans, std::stoi(s.substr(0, i)) + std::stoi(s.substr(i)));
	}

	std::cout << ans << "\n";
}

C. 小苯的Z串匹配

从前往后枚举,发现每个数的符号都是确定的。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<i64> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::string s;
    std::cin >> s;
    int ans = 0;
    for (int i = 0; i < n; ++ i) {
    	if (s[i] == '<') {
    		ans += a[i] >= 0;
    		a[i] = -1;
    	} else if (s[i] == '>') {
    		ans += a[i] <= 0;
    		a[i] = 1;
    	} else {
    		if (a[i] * a[i - 1] <= 0) {
    			a[i] = a[i - 1];
    			++ ans;
    		}
    	}
    }

    std::cout << ans << "\n";
}

D. 小苯的最大和

题意:给你一个数组,每次可以删去连续的两个数,或者连续的三个数,求剩下的数和最大。

发现如果连续的负数区间长度大于1,就可以都删去,那么数组就变成了一正一负交替的情况。
那么对于这个新数组,设长度为\(m\),我们可以考虑dp。\(f_i\)表示值为前\(i\)个数的最大和。
\(f_i = \max(f_{i-1} + a_i, f_{i-2}, f_{i-3})\),意味不删\(a_i\),删\(a_i, a_{i-1}\),删\(a_i, a_{i-1}, a_{i-2}\)的最大值。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n), b;
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }
    for (int i = 0; i < n; ++ i) {
    	if (a[i] < 0) {
    		int j = i;
    		while (j < n && a[j] < 0) {
    			++ j;
    		}

    		-- j;
    		if (i == j) {
    			b.push_back(a[i]);
    		}

    		i = j;
    	} else {
    		b.push_back(a[i]);
    	}
    }

    int m = b.size();
    if (m == 0) {
    	std::cout << 0 << "\n";
    	return;
    }
    std::vector<i64> f(m + 1, -1e18);
    f[0] = 0; f[1] = b[0];
    for (int i = 2; i <= m; ++ i) {
    	f[i] = f[i - 1] + b[i - 1];
    	f[i] = std::max(f[i], f[i - 2]);
    	if (i > 2) {
    		f[i] = std::max(f[i], f[i - 3]);
    	}
    }

    std::cout << f[m] << "\n";
}

E. 小苯的数组构造

题意:构造一个元素都大于0的数组,使得或和为\(x\),异或和为\(y\)

按位考虑。
如果\(y\)里有\(x\)没有的位,无解。
否则如果第\(i\)\(x\)为一,那么如果\(y\)这一位为1,说明这一位出现奇数次,否则\(y\)这一位为\(0\),说明出现偶数次。
那么我们可以把这些为均匀的给数组的每一个数。因为可能这些为给的数不足\(n\)个,那么为了能让每一个数都大于0,我是先从前往后给,下一次从后往前给,如此循环,最后判断一下。

点击查看代码
void solve() {
    int n, x, y;
    std::cin >> n >> x >> y;
    if ((x | y) != x) {
    	std::cout << "NO\n";
    	return;
    }

    std::vector<int> a(n);    

    int f0 = 0, f1 = 1;
    for (int i = 0; i < 31; ++ i) {
    	if ((x >> i & 1) && !(y >> i & 1)) {
    		if (f0 == 0) {
    			for (int j = 0; j < n - n % 2; ++ j) {
	    			a[j] += 1 << i;
	    		}
	    	} else {
	    		for (int j = n - 1; j >= n % 2; -- j) {
	    			a[j] += 1 << i;
	    		}
	    	}
	    	f0 ^= 1;
    	} else if ((x >> i & 1) && (y >> i & 1)) {
    		if (f1 == 0) {
    			for (int j = 0; j < n - (n % 2 == 0); ++ j) {
	    			a[j] += 1 << i;
	    		}
	    	} else {
	    		for (int j = n - 1; j >= (n % 2 == 0); -- j) {
	    			a[j] += 1 << i;
	    		}
	    	}

	    	f1 ^= 1;
    	}
    }

    int xx = 0, yy = 0;
    for (int i = 0; i < n; ++ i) {
    	xx |= a[i];
    	yy ^= a[i];
    	if (a[i] == 0) {
    		std::cout << "NO\n";
    		return;
    	}
    }

    if (xx != x || yy != y) {
    	std::cout << "NO\n";
    	return;
    } else {
    	std::cout << "YES\n";
    	for (int i = 0; i < n; ++ i) {
    		std::cout << a[i] << " \n"[i == n - 1];
    	}
    }
}

F. 小苯的ovo2.0

题意:给你一个只包含, 'o', 'v', '?'的字符串,更改'?'使得"ovo"作为子序列出现的次数最多。

猜测'v'在中间更好。
那么我们枚举某一段区间的'?'都变成'v',外面的都变成'o',去最大值。
那么给一个只包含'o', 'v'的字符串,如何求"ovo"子序列的出现次数,可以从前往后,记录'o'的个数和"ov"的个数,每次遇到'o'答案加上"ov"的个数,并使的'o'的个数加一,遇到'v'使得"ov"的个数加上'o'的个数。

点击查看代码
void solve() {
    std::string s;
    std::cin >> s;
    int n = s.size();
    auto get = [&](int l, int r) -> int {
    	int s1 = 0, s2 = 0;
    	int res = 0;
    	for (int i = 0; i < n; ++ i) {
    		if (s[i] == 'o' || (s[i] == '?' && (i < l || i > r))) {
    			res += s2;
    			s1 += 1;
    		} else if (s[i] == 'v' || (s[i] == '?' && i >= l && i <= r)) {
    			s2 += s1;
    		}
    	}

    	return res;
    };

    int ans = 0;
    for (int i = 0; i < n; ++ i) {
    	for (int j = i; j < n; ++ j) {
    		ans = std::max(ans, get(i, j));
    	}
    }

    std::cout << ans << "\n";
}
posted @ 2025-03-30 21:19  maburb  阅读(79)  评论(0)    收藏  举报