A
栈维护括号匹配,\(S \to (, T \to )\)。
#include <bits/stdc++.h>using i64 = long long;void solve() {std::string s;std::cin >> s;std::stack<char> stc;for (auto i : s) {if (i == 'T' && stc.size()) {if (stc.top() == 'S') {stc.pop(); continue;}}stc.push(i);}std::cout << stc.size() << "\n";
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);solve();return 0;
}
B
一开始看错题了,注意题目表达的是“所有子区间最小值之和”,考虑平衡树。将所有元素按照 \((a_i, i)\) 绑入,按照 \(a_i\) 的大小排序之后按次插入平衡树中,每次去找当前位置的前驱后继就可以了,统计答案是简单的乘法原理。
#include <bits/stdc++.h>
#include <bits/extc++.h> using i64 = long long;constexpr int N = 2e5 + 7;int n;
i64 ans;struct Elem {int v, i;bool operator < (const Elem &rhs) const {return v < rhs.v;}
};int a[N];std::vector<Elem> vec;
__gnu_pbds::tree<int, __gnu_pbds::null_type, std::less<int>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update> tr;int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cin >> n;for (int i = 1; i <= n; i++) {std::cin >> a[i];vec.push_back({a[i], i});}std::sort(vec.begin(), vec.end());tr.insert(0); tr.insert(n + 1);for (const auto &[v, i] : vec) {int l = i - *tr.upper_bound(i), r = *std::prev(tr.lower_bound(i)) - i;ans += 1ll * v * l * r;tr.insert(i);}std::cout << ans << "\n";return 0;
}
C
究极无敌简单题。考虑树上最远距离就是直径,找到距离最远的两个点抓出来做匹配,容易发现其实就是走到中点前降、走过中点之后升的这么一个过程,开桶每次匹配两个上去,如果匹配不上报告无解。
#include <bits/stdc++.h>using i64 = long long;constexpr int N = 107;int n, mxd;
int a[N], cnt[N];int work() {int mid = mxd / 2 + 1;for (int i = mid; i <= mxd; i++) {cnt[i] -= 2;if (cnt[i] < 0)return 0;} if (!(mxd & 1)) {cnt[mid - 1]--;if (cnt[mid - 1] < 0)return 0;mid--;}for (int i = 1; i <= mid; i++) {if (cnt[i])return 0;}return 1;
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cin >> n;for (int i = 1; i <= n; i++) {std::cin >> a[i];cnt[a[i]]++;mxd = std::max(mxd, a[i]);}std::cout << (work() ? "Possible" : "Impossible") << "\n";return 0;
}