大意:求出給定長度為
解法:可以把這個序列切成很多嚴格下降子區間——當
時間複雜度:
空間複雜度:
#include <bits/stdc++.h>
#define ALL(x) begin(x), end(x)
using namespace std;
using i64 = long long;
template <class T>
using vec = vector<T>;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n; cin >> n;
int pre = numeric_limits<int>::max() / 2;
int ans = 0;
for (int x, cnt = 0; n--; ) {
cin >> x;
if (x >= pre) cnt = 0;
ans = max(ans, ++cnt);
pre = x;
}
cout << ans << '\n';
}
大意:有
解法:每次操作都去看所有格子有沒有滿足上面講的條件,如果有的話才把值加上
時間複雜度:
空間複雜度:
#include <bits/stdc++.h>
#define ALL(x) begin(x), end(x)
using namespace std;
using i64 = long long;
template <class T>
using vec = vector<T>;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int h, w, q; cin >> h >> w >> q;
vec<int> val(h * w, 0);
for (int r, c, t, x; q--; ) {
cin >> r >> c >> t >> x;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
if (abs(r - i) + abs(c - j) <= t) val[i * w + j] += x;
}
}
}
for (int i = 0; i < h * w; i++) cout << val[i] << " \n"[(i + 1) % w == 0];
}
大意:給定一個大小為
解法:先預處理每個字母在字母集中比多少人大,記為
另一個解法是:先把
第一種解法的時間複雜度:
第二種解法的時間複雜度:
#include <bits/stdc++.h>
#define ALL(x) begin(x), end(x)
using namespace std;
using i64 = long long;
template <class T>
using vec = vector<T>;
constexpr int maxN = 300000;
bitset<maxN> vis;
int pre[26];
char mp[10];
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int S_len = 0;
auto id = [](char c) -> int { return pre[c - 'a'] - 1; };
{
string s; cin >> s;
S_len = s.length();
for (auto c : s) ++pre[c - 'a'];
for (int i = 1; i < 26; i++) pre[i] += pre[i - 1];
for (auto c : s) mp[id(c)] = c;
}
int len; cin >> len;
string s; cin >> s;
int N = (int)s.length();
int hash_val = 0, mul = 1;
for (int i = 0; i < len; i++) {
hash_val = hash_val * S_len + id(s[i]);
if (i) mul *= S_len;
}
if (hash_val < N) vis[hash_val] = true;
for (int i = len; i < N; i++) {
hash_val -= id(s[i - len]) * mul;
hash_val = hash_val * S_len + id(s[i]);
if (hash_val < N) vis[hash_val] = true;
}
string ans;
int x = [&]() -> int {
for (int i = 0; i < N; i++) if (!vis[i]) return i;
return N;
}();
for (int t = len; t--; ) {
ans.push_back(mp[(x % S_len)]);
x /= S_len;
}
reverse(ALL(ans));
cout << ans << '\n';
}
大意:給一個長度為
解法:可以拿的其實是一個前綴和一個不和那個前綴重疊的後綴,所以對每個前綴和
時間複雜度:
空間複雜度:
#include <bits/stdc++.h>
#define ALL(x) begin(x), end(x)
using namespace std;
using i64 = long long;
template <class T>
using vec = vector<T>;
constexpr int maxDIFF = 2000;
vec<pair<int, int>> pref[maxDIFF * 2 + 1];
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
auto add = [](int diff, int pre, int i) -> void {
pref[diff + maxDIFF].emplace_back(pre, i);
};
auto is_empty = [](int diff) -> bool {
return pref[diff + maxDIFF].empty();
};
auto top = [](int diff) {
return pref[diff + maxDIFF].back();
};
auto pop = [](int diff) -> void {
pref[diff + maxDIFF].pop_back();
};
int n, k; cin >> n >> k;
vec<int> v(n);
for (int i = 0, diff = 0, pre = 0; i < n; i++) {
cin >> v[i];
diff += ((v[i] & 1) ? 1 : -1);
pre += v[i];
add(diff, pre, i);
}
int ans = ((is_empty(0) || top(0).first > k) ? 0 : top(0).first);
for (int i = n - 1, diff = 0, suf = 0; i >= 0; i--) {
diff += ((v[i] & 1) ? 1 : -1);
suf += v[i];
if (suf > k) break;
if (diff < -maxDIFF || diff > maxDIFF) continue;
while (!is_empty(-diff) && (top(-diff).second >= i || top(-diff).first + suf > k)) pop(-diff);
if (diff == 0) ans = max(ans, suf);
if (!is_empty(-diff)) ans = max(ans, suf + top(-diff).first);
}
cout << ans << '\n';
}
CSES Advanced Techniques題解
May 12, 2025CDQ分治題,但我不要CDQ分治。
Feb 21, 2024注意到每一句只有第二、四、六、七個字會用到,而且可以把句子第二、四、六個字的平仄轉成整數來判斷。第一個規則代表上下聯一定要是{010}_2(={2}_{10})或{101}_2(={5}_{10});第二個規則可以直接判斷;第三個規則則是上下聯bitwise xor要是7_{10}(={111}_{2}),也就是每個位置都不同。
Oct 15, 2023去除重複元素然後排序,因為我很懶所以用set<int, greater<int> >。
Oct 13, 2023or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up