C - Attention
前后缀搞一搞即可。Code
#include <bits/stdc++.h> #define MP make_pair #define fi first #define se second #define sz(x) (int)(x).size() //#define Local using namespace std; typedef long long ll; typedef pair<int, int> pii; const int N = 3e5 + 5; int n; char s[N]; int pre[N], suf[N]; void run() { cin >> s + 1; for(int i = 1; i <= n; i++) { pre[i] = pre[i - 1]; if(s[i] == 'W') ++pre[i]; } suf[n + 1] = 0; for(int i = n; i >= 1; i--) { suf[i] = suf[i + 1]; if(s[i] == 'E') ++suf[i]; } int ans = n + 1; for(int i = 1; i <= n; i++) { ans = min(ans, pre[i - 1] + suf[i + 1]); } cout << ans << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cout << fixed << setprecision(20); #ifdef Local freopen("../input.in", "r", stdin); freopen("../output.out", "w", stdout); #endif while(cin >> n) run(); return 0; }
D - Xor Sum 2
题意:
给出一个长度为\(n\)的序列\(a\),现在问有多少区间\([l,r]\),满足:
\[
a_l\ xor\ a_{l+1}\ xor \cdots \ xor\ x_r=a_l+a_{l+1}+\cdots+a_r
\]
思路:
注意这样一个性质:\(a_i\ xor\ a_j\leq a_i+a_j\)。
所以一旦一个区间不满足条件过后,更大的区间也不满足了;一个区间满足条件,更小的区间也满足。
所以直接双指针搞搞就行。Code
#include <bits/stdc++.h> #define MP make_pair #define fi first #define se second #define sz(x) (int)(x).size() //#define Local using namespace std; typedef long long ll; typedef pair<int, int> pii; const int N = 2e5 + 5; int n; int a[N]; void run() { for(int i = 1; i <= n; i++) cin >> a[i]; int j = 0; ll sum1 = 0, sum2 = 0; ll ans = 0; for(int i = 1; i <= n; i++) { while(j + 1 <= n) { if(sum1 + a[j + 1] == (sum2 ^ a[j + 1])) { sum1 += a[++j], sum2 ^= a[j]; } else break; } ans += j - i + 1; sum1 -= a[i]; sum2 ^= a[i]; } cout << ans << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cout << fixed << setprecision(20); #ifdef Local freopen("../input.in", "r", stdin); freopen("../output.out", "w", stdout); #endif while(cin >> n) run(); return 0; }
E - Range Minimum Queries
题意:
给出一个长度为\(n\)的序列\(a\),现在执行\(q\)次操作,每次选择一段长度为\(k\)的区间,删除一个最小的数(如果有多个,可任意删除一个)。
最后问在所有删除的数中,相差最小为多少。
思路:
- 很容易想到二分差值,然后枚举下界,这样就知道了上下界。
- 因为每次必须选择最小的一个数,所以所有大于等于下界的数构成了一个个可执行区间(因为若区间中含小于的数那肯定不合法),每次在这些区间里面贪心选就行。
详见代码:Code
#include <bits/stdc++.h> #define MP make_pair #define fi first #define se second #define sz(x) (int)(x).size() //#define Local using namespace std; typedef long long ll; typedef pair<int, int> pii; const int N = 2005; int n, k, q; int a[N]; bool chk(int x) { for(int i = 1; i <= n; i++) { int Min = a[i]; int res = 0; for(int l = 1, r; l <= n; l = r) { r = l; if(a[l] < Min) { ++r; continue; } int cnt = 0; while(r <= n && a[r] >= Min) { if(a[r] <= Min + x) ++cnt; ++r; } if(r - l >= k) res += min(r - l + 1 - k, cnt); } if(res >= q) return true; } return false; } void run() { for(int i = 1; i <= n; i++) cin >> a[i]; int l = 0, r = 1e9 + 1, mid; while(l < r) { mid = (l + r) >> 1; if(chk(mid)) r = mid; else l = mid + 1; } cout << l << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cout << fixed << setprecision(20); #ifdef Local freopen("../input.in", "r", stdin); freopen("../output.out", "w", stdout); #endif while(cin >> n >> k >> q) run(); return 0; }
F - Donation
题意:
给出一个无向图,选定一个起点,一开始有\(W\)元,之后可以选择走向相邻一个节点或者给当前结点捐赠\(b_i\)元,若走向一个结点至少得有\(a_i\)元才行。
现在确定一个最小的\(W\)以及一个起点,使得最终能够顺利捐赠成功每个点。
思路:
还有点没想清楚,先埋个坑。