给出两个序列,有R有B,每次操作可以将一个序列后面的自负拿出来放到另一个序列的后面。是否能通过若干次操作,使得每一序列的相邻两个字符都不同。
思路:将其中一个序列翻转,判断一下即可。
AC Code:
#include typedef long long ll;
const int N = 1e5 + 5;
int t, n, m;
std::string a, b;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);std::cin >> t;while(t --) {std::cin >> n >> m;std::cin >> a >> b;reverse(a.begin(), a.end());b = b + a;bool flag = true;int cnt = 0;for(int i = 1; i < n + m; i ++) {if(b[i] == b[i - 1]) {if(b[i] != b[i + 1] || i == n + m - 1)cnt ++;if(b[i] == b[i + 1] || cnt > 1) {flag = false;break;}}}std::cout << (flag ? "YES" : "NO") << '\n';}return 0;
}
给出若干个区间,给出目标点k,问是否可以通过去掉若干个区间使得目标点在剩余区间的出现次数是最多的。
思路:对于每一个包含目标点的区间,缩小它的左右端点,若所有的区间内只有k出现次数最多才能满足条件。
AC Code:
#include typedef long long ll;
const int N = 105;
int t, n, k;
int l, r;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);std::cin >> t;while(t --) {std::cin >> n >> k;int L = -100, R = 100;for(int i = 1; i <= n; i ++) {std::cin >> l >> r;if(l <= k && r >= k)L = std::max(l, L), R = std::min(r, R);}if(L == R && L == k) std::cout << "YES" << '\n';elsestd::cout << "NO" << '\n';}return 0;
}
给出n个人的喝茶的数量,和n种茶的数量,一开始i号人喝i号茶,然后向前走,i号人喝i-1号茶,求最后每个人能喝多少茶。
思路:求所有人喝茶数的前缀和,对于每种茶二分查找使得每个人能喝到自己预定的数量的茶,开头结尾两个点做差分标记,剩余的茶给下一个。然后每个人根据差分求前缀和得到答案。
AC Code:
#include typedef long long ll;
const int N = 2e5 + 5;
int t, n;
ll a[N], b[N], pre[N], ans[N], dif[N];int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);std::cin >> t;while(t --) {std::cin >> n;for(int i = 0; i <= n + 1; i ++) {dif[i] = pre[i] = ans[i] = 0;}for(int i = 1; i <= n; i ++) {std::cin >> a[i];}for(int i = 1; i <= n; i ++) {std::cin >> b[i];pre[i] = pre[i - 1] + b[i];}for(int i = 1; i <= n; i ++) {int pos = std::lower_bound(pre + 1, pre + 1 + n, a[i] + pre[i - 1]) - pre;if(pre[pos] > a[i] + pre[i - 1] || pos == n + 1)pos --;dif[i] ++, dif[pos + 1] --;ans[pos + 1] += a[i] + pre[i - 1] - pre[pos]; }for(int i = 1; i <= n; i ++) {dif[i] += dif[i - 1];ans[i] += dif[i] * b[i];std::cout << ans[i] << " \n"[i == n];}}return 0;
}
给出n个点,每三个分到一组中并两两相连,每条边有一个权值,且分成的三元组是偶数个。现在需要对每个点进行染色,染色需要满足两个条件,染色的颜色有红蓝两种,每种颜色染色的点必须是点数的一半。对于每种不同的染色,它的值是所有连着不同颜色点的边的权值之和。求最大的染色的值的种类有多少种。
思路:显然,每一个三元组对答案的最大贡献是两条边,既然要取到最大权值,那必然是每个三元组都贡献两条最长的边。计算种类时,对于一种颜色,要有一半的三元组是染两个点,这样的种类数是C(n / 3, n / 6)。然后在一个三元组中,当三条边同样长时,对答案的贡献是三种,即任意一个点染其他颜色;对于两条较短边一样长时,取最长边和任意一条短边,这样是两种选法,乘起来即可。
AC Code:
#include typedef long long ll;
const int N = 3e5 + 5;
int t, n;
ll w[N];template
struct ModInt {const static int mod = T;int x;ModInt(int x = 0) : x(x % mod) {}ModInt(ll x) : x(int(x % mod)) {} int val() { return x; }ModInt operator + (const ModInt &a) const { int x0 = x + a.x; return ModInt(x0 < mod ? x0 : x0 - mod); }ModInt operator - (const ModInt &a) const { int x0 = x - a.x; return ModInt(x0 < 0 ? x0 + mod : x0); }ModInt operator * (const ModInt &a) const { return ModInt(1LL * x * a.x % mod); }ModInt operator / (const ModInt &a) const { return *this * a.inv(); }void operator += (const ModInt &a) { x += a.x; if (x >= mod) x -= mod; }void operator -= (const ModInt &a) { x -= a.x; if (x < 0) x += mod; }void operator *= (const ModInt &a) { x = 1LL * x * a.x % mod; }void operator /= (const ModInt &a) { *this = *this / a; }friend std::ostream &operator<<(std::ostream &os, const ModInt &a) { return os << a.x;}ModInt pow(int64_t n) const {ModInt res(1), mul(x);while(n){if (n & 1) res *= mul;mul *= mul;n >>= 1;}return res;}ModInt inv() const {int a = x, b = mod, u = 1, v = 0;while (b) {int t = a / b;a -= t * b; std::swap(a, b);u -= t * v; std::swap(u, v);}if (u < 0) u += mod;return u;}};
typedef ModInt<998244353> mint;mint fact[N], invfact[N];void init(){fact[0] = invfact[0] = 1;for(int i = 1; i < N; i++) fact[i] = fact[i - 1] * i;invfact[N - 1] = fact[N - 1].inv();for(int i = N - 2; i; i--)invfact[i] = invfact[i + 1] * (i + 1);
}inline mint C(int a, int b){if (a < 0 || b < 0 || a < b) return 0;return fact[a] * invfact[b] * invfact[a - b];
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);init();std::cin >> n;for(int i = 1; i <= n; i ++) {std::cin >> w[i];}mint ans = 1;int a[4] = {0};for(int i = 1; i <= n / 3; i ++) {a[3] = std::max({w[i * 3 - 2], w[i * 3 - 1], w[i * 3]});a[1] = std::min({w[i * 3 - 2], w[i * 3 - 1], w[i * 3]});a[2] = w[i * 3 - 2] + w[i * 3 - 1] + w[i * 3] - a[1] - a[3];if(a[1] == a[2] && a[1] == a[3]) ans *= 3;else if(a[1] == a[2])ans *= 2;}ans *= C(n / 3, n / 6);std::cout << ans << '\n';return 0;
}
os:这个自动取模的板子太好用了吧!