A. Shape Perimeter
#include <bits/stdc++.h>
#define int long long
void Solve() {
int n, m;
std::cin >> n >> m;
int ans = m * 4 * n;
for (int i = 0; i < n; ++i) {
int x, y;
std::cin >> x >> y;
if (!i) {
continue;
}
ans -= 2 * (m + m - x - y);
}
std::cout << ans << '\n';
}
signed main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
for (int ti = 1; ti <= t; ++ti) {
// std::cerr << "Solve : " << ti << '\n';
Solve();
}
return 0;
}
B. Find the Permutation
#include <bits/stdc++.h>
#define int long long
void Solve() {
int n;
std::cin >> n;
std::vector a(n, std::vector<int>(n, 0));
for (int i = 0; i < n; ++i) {
std::string s;
std::cin >> s;
for (int j = 0; j < n; ++j) {
a[i][j] = s[j] - '0';
}
}
std::vector<int> ans(n);
for (int i = n - 1; i >= 0; --i) {
int s = 0;
for (int j = 0; j < i; ++j) {
s += a[i][j];
}
int cnt = 0;
for (int j = 0; j < n; ++j) {
if (cnt == s && !ans[j]) {
ans[j] = i + 1;
break;
}
cnt += !ans[j];
}
}
for (int i = 0; i < n; ++i) {
std::cout << ans[i] << ' ';
}
std::cout << '\n';
}
signed main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
for (int ti = 1; ti <= t; ++ti) {
// std::cerr << "Solve : " << ti << '\n';
Solve();
}
return 0;
}
C. Palindromic Subsequences
发现1 2 3 4 5 … 1 2 3 4 5 是可行的,不过需要特判一下n=6/7的情况
#include <bits/stdc++.h>
#define int long long
void Solve() {
int n;
std::cin >> n;
if (n == 6) {
std::cout << "1 1 2 3 1 2\n";
return;
}
if (n == 7) {
std::cout << "1 1 2 3 1 2 3\n";
return;
}
for (int i = 1; i <= n / 2; ++i) std::cout << i << ' ';
for (int i = 1; i <= n - n / 2; ++i) std::cout << i << ' ';
std::cout << '\n';
}
signed main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
for (int ti = 1; ti <= t; ++ti) {
// std::cerr << "Solve : " << ti << '\n';
Solve();
}
return 0;
}
D. Unique Median
乍一看没什么思路,正难则反,考虑将所有区间减去不合法的区间
枚举分界点 i i i,假设我们其中一个中位数是 i i i,另一个是 i + 1 i+1 i+1,一个很经典的trick是把 ≤ i \leq i ≤i的数记 a i = 1 a_i=1 ai=1,把 > i >i >i的数记 a i = − 1 a_i=-1 ai=−1,那么区间 [ l , r ] [l, r] [l,r]是不合法的当且仅当 ∑ k = l r a k = 0 \sum_{k=l}^r a_k=0 ∑k=lrak=0
记 s i = s i − 1 + a i s_i=s_{i-1}+a_i si=si−1+ai,则条件转化为 s r − s l − 1 = 0 s_r-s_{l-1}=0 sr−sl−1=0,需要注意算重的情况
时间复杂度 O ( 10 n ) O(10n) O(10n),我偷懒用了map多一个log,也能过
#include <bits/stdc++.h>
#define int long long
constexpr int N = 1e5 + 5;
int n;
int a[N], val[N];
void Solve() {
std::vector<int> vis(11);
std::cin >> n;
for (int i = 1; i <= n; ++i) {
std::cin >> a[i];
vis[a[i]] = 1;
}
int ans = n * (n + 1) / 2;
for (int i = 1; i <= 9; ++i) {
if (!vis[i]) continue;
std::map<int, int> cnt;
val[0] = 0;
int cur = 0;
int pos = 0;
for (int j = 1; j <= n; ++j) {
if (a[j] > i) {
++cur;
} else {
--cur;
}
if (a[j] == i) {
while (pos < j) {
cnt[val[pos]]++;
pos++;
}
}
ans -= cnt[cur];
val[j] = cur;
}
// std::cerr << "i = " << i << " ans = " < < ans << '\n';
}
std::cout << ans << '\n';
}
signed main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
for (int ti = 1; ti <= t; ++ti) {
// std::cerr << "Solve : " << ti << '\n';
Solve();
}
return 0;
}
E. Nested Segments
哥哥的组合数板子是真的好用!!!
强推!!!!!
一开始想复杂了,以为是神秘计数poly题
考虑分治,使用set递归找出所有极大的区间(有一些细节见代码,边界问题很容易错),依次删除,然后你会剩下一些空子,是经典的括号匹配问题(卡特兰数(使用递推求解)),所有方案数相乘即可
F1看起来是高精度好可怕,跑路了跑路了(doge)
今天看了一下好像并不需要高精度捏。。。
#include <bits/stdc++.h>
#define int long long
template<class T>
constexpr T power(T a, int b) {
T res {1};
for (; b; b /= 2, a *= a) {
if (b % 2) {
res *= a;
}
}
return res;
}
constexpr int mul(int a, int b, int p) {
int res = a * b - (int)(1.L * a * b / p) * p;
res %= p;
if (res < 0) {
res += p;
}
return res;
}
template<int P>
struct MInt {
int x;
constexpr MInt() : x {0} {}
constexpr MInt(int x) : x {norm(x % getMod())} {}
static int Mod;
constexpr static int getMod() {
if (P > 0) {
return P;
} else {
return Mod;
}
}
constexpr static void setMod(int Mod_) {
Mod = Mod_;
}
constexpr int norm(int x) const {
if (x < 0) {
x += getMod();
}
if (x >= getMod()) {
x -= getMod();
}
return x;
}
constexpr int val() const {
return x;
}
constexpr MInt operator-() const {
MInt res;
res.x = norm(getMod() - x);
return res;
}
constexpr MInt inv() const {
return power(*this, getMod() - 2);
}
constexpr MInt &operator*=(MInt rhs) & {
if (getMod() < (1ULL << 31)) {
x = x * rhs.x % (int)(getMod());
} else {
x = mul(x, rhs.x, getMod());
}
return *this;
}
constexpr MInt &operator+=(MInt rhs) & {
x = norm(x + rhs.x);
return *this;
}
constexpr MInt &operator-=(MInt rhs) & {
x = norm(x - rhs.x);
return *this;
}
constexpr MInt &operator/=(MInt rhs) & {
return *this *= rhs.inv();
}
friend constexpr MInt operator*(MInt lhs, MInt rhs) {
MInt res = lhs;
res *= rhs;
return res;
}
friend constexpr MInt operator+(MInt lhs, MInt rhs) {
MInt res = lhs;
res += rhs;
return res;
}
friend constexpr MInt operator-(MInt lhs, MInt rhs) {
MInt res = lhs;
res -= rhs;
return res;
}
friend constexpr MInt operator/(MInt lhs, MInt rhs) {
MInt res = lhs;
res /= rhs;
return res;
}
friend constexpr std::istream &operator>>(std::istream &is, MInt &a) {
int v;
is >> v;
a = MInt(v);
return is;
}
friend constexpr std::ostream &operator<<(std::ostream &os, const MInt &a) {
return os << a.val();
}
friend constexpr bool operator==(MInt lhs, MInt rhs) {
return lhs.val() == rhs.val();
}
friend constexpr bool operator!=(MInt lhs, MInt rhs) {
return lhs.val() != rhs.val();
}
};
template<>
int MInt<0>::Mod = 998244353;
constexpr int P = 998244353;
using Z = MInt<P>;
struct Comb {
int n;
std::vector<Z> _fac;
std::vector<Z> _invfac;
std::vector<Z> _inv;
Comb() : n{0}, _fac{1}, _invfac{1}, _inv{0} {}
Comb(int n) : Comb() {
init(n);
}
void init(int m) {
m = std::min<int>(m, Z::getMod() - 1);
if (m <= n) return;
_fac.resize(m + 1);
_invfac.resize(m + 1);
_inv.resize(m + 1);
for (int i = n + 1; i <= m; i++) {
_fac[i] = _fac[i - 1] * i;
}
_invfac[m] = _fac[m].inv();
for (int i = m; i > n; i--) {
_invfac[i - 1] = _invfac[i] * i;
_inv[i] = _invfac[i] * _fac[i - 1];
}
n = m;
}
Z fac(int m) {
if (m > n) init(2 * m);
return _fac[m];
}
Z invfac(int m) {
if (m > n) init(2 * m);
return _invfac[m];
}
Z inv(int m) {
if (m > n) init(2 * m);
return _inv[m];
}
Z binom(int n, int m) {
if (n < m || m < 0) return 0;
return fac(n) * invfac(m) * invfac(n - m);
}
} comb;
constexpr int N = 2e5 + 5;
Z cat[N];
void Solve() {
int n, m;
std::cin >> n >> m;
auto Cmp = [&](std::pair<int, int> a, std::pair<int, int> b) {
if (a.first == b.first) {
return a.second > b.second;
}
return a.first < b.first;
};
std::set<std::pair<int, int>, decltype(Cmp)> st{Cmp};
st.emplace(1, n);
for (int i = 0; i < m; ++i) {
int l, r;
std::cin >> l >> r;
st.emplace(l, r);
}
Z ans = 1;
auto dc = [&](auto &&self, int l, int r) -> void {
// std::cerr << "divide : " << l << " " << r << '\n';
int len = r - l;
st.erase({l, r});
std::vector<std::pair<int, int>> seg;
auto it = st.lower_bound({l, r});
while (it != st.end()) {
auto [x, y] = *it;
// std::cerr << x << ' ' << y << '\n';
if (x > r) {
break;
}
len -= y - x;
seg.emplace_back(x, y);
it = st.lower_bound({y + 1, r});
}
// std::cerr << "len : " << len << '\n';
// std::cerr << "seg : ";
// for (auto [x, y] : seg) {
// std::cerr << x << " " << y << " ";
// }
// std::cerr << '\n';
ans *= cat[len];
for (auto [x, y] : seg) {
self(self, x, y);
}
};
dc(dc, 1, n);
std::cout << ans << '\n';
}
signed main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
cat[0] = cat[1] = 1;
for (int i = 2; i < N; ++i) {
cat[i] = cat[i - 1] * (4 * i - 2) / (i + 1);
}
for (int ti = 1; ti <= t; ++ti) {
// std::cerr << "Solve : " << ti << '\n';
Solve();
}
return 0;
}