topcoder srm 702 div1
problem1 link
从1到$n*m$,依次枚举。每次将当前数字填回正确位置。比较该次操作前后是否变大。不变大则不做本次操作。
problem2 link
首先得到所有合法的字符串,然后分别枚举是不是$S$的子列。
problem3 link
https://blog.csdn.net/qq_35649707/article/details/83894852
二分答案.然后对于固定的$k$, 对于每个位置$i$,计算$L[i], R[i]$表示左右最近的不超过$k$的数字的下标.然后可以判断是否存在一个不小于$m$的区间满足要求.
code for problem1
#include <string> #include <vector> class GridSortMax { public: std::string findMax(int n, int m, const std::vector<int> &grid) { this->n = n; this->m = m; a.resize(n, std::vector<int>(m)); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { a[i][j] = grid[i * m + j]; } } for (int i = 1; i <= n * m; ++i) { int x = 0, y = 0; Get(i, &x, &y); int xx = (i - 1) / m; int yy = (i - 1) % m; if (x == xx && y == yy) { continue; } std::string s0 = ToString(); std::vector<std::vector<int>> b = a; if (x != xx) { SwapRow(x, xx); } if (y != yy) { SwapCol(y, yy); } std::string s1 = ToString(); if (s1 < s0) { a = b; } } return ToString(); } private: void SwapCol(int y1, int y2) { for (int i = 0; i < n; ++i) { std::swap(a[i][y1], a[i][y2]); } } void SwapRow(int x1, int x2) { std::swap(a[x1], a[x2]); } std::string ToString() { std::string s = ""; for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) { if (a[i][j] == i * m + j + 1) { s += "1"; } else { s += "0"; } } return s; } void Get(int t, int *x, int *y) { for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (a[i][j] == t) { *x = i; *y = j; return; } } } } std::vector<std::vector<int>> a; int n, m; };
code for problem2
#include <set> #include <string> class RepeatedStrings { public: std::string findKth(const std::string& S, int k) { Dfs("()"); for (const auto& x : s) { size_t p1 = 0, p2 = 0; while (p1 < S.size() && p2 < x.size()) { if (S[p1] == x[p2]) { ++p1; ++p2; } else { ++p1; } } if (p2 >= x.size()) { if (--k == 0) { return x; } } } return ""; } private: void Dfs(std::string x) { constexpr size_t kMax = 150; if (x.size() > kMax) { return; } s.insert(x); std::string p = ""; while (p.size() <= kMax) { p += x; Dfs("(" + p + ")"); } } std::set<std::string> s; };
code for problem3
#include <algorithm> #include <memory> #include <vector> struct SegmentTree { SegmentTree(const std::vector<int> &a) : n(static_cast<int>(a.size())), a(a), tree(n << 4) {} void Clear() { Clear(1, 0, n - 1); } void Update(int x, int v) { Update(1, x, v); } int Get(int l, int r, bool is_min) { if (l < a[0]) { l = a[0]; } if (r > a.back()) { r = a.back(); } if (l > r) { return -1; } return Get(1, l, r, is_min); } private: void Clear(int t, int l, int r) { tree[t].l = l; tree[t].r = r; tree[t].min_index = tree[t].max_index = -1; if (l == r) { return; } int m = (l + r) >> 1; Clear(t * 2, l, m); Clear(t * 2 + 1, m + 1, r); } void Update(int t, int x, int v) { if (tree[t].min_index == -1 || v < tree[t].min_index) { tree[t].min_index = v; } if (tree[t].max_index == -1 || v > tree[t].max_index) { tree[t].max_index = v; } if (tree[t].l == tree[t].r) { return; } int m = (tree[t].l + tree[t].r) >> 1; if (x <= a[m]) { Update(t * 2, x, v); } else { Update(t * 2 + 1, x, v); } } int Get(int t, int min_v, int max_v, bool is_min) { if (a[tree[t].l] >= min_v && a[tree[t].r] <= max_v) { return is_min ? tree[t].min_index : tree[t].max_index; } if (tree[t].l == tree[t].r) { return -1; } int m = (tree[t].l + tree[t].r) >> 1; int lid = -1; int rid = -1; if (min_v <= a[m]) { lid = Get(t * 2, min_v, max_v, is_min); } if (max_v >= a[m + 1]) { rid = Get(t * 2 + 1, min_v, max_v, is_min); } if (lid == -1) { return rid; } else if (rid == -1) { return lid; } else { return is_min ? std::min(lid, rid) : std::max(lid, rid); } } struct Node { int l, r; int min_index; int max_index; }; int n; const std::vector<int> &a; std::vector<Node> tree; }; class FindingFriends { public: int shortestDistance(int n, const std::vector<int> &init, int A, int b, int c, int d, int m) { this->n = n; this->m = m; a.resize(n); int num = static_cast<int>(init.size()); int min = init[0]; int max = init[0]; for (int i = 0; i < num; ++i) { a[i] = init[i]; min = std::min(min, a[i]); max = std::max(max, a[i]); } for (int i = num; i < n; ++i) { a[i] = (1ll * a[i - 1] * A + 1ll * b * i + c) % d; min = std::min(min, a[i]); max = std::max(max, a[i]); } ua = a; std::sort(ua.begin(), ua.end()); ua.erase(std::unique(ua.begin(), ua.end()), ua.end()); tree = std::unique_ptr<SegmentTree>(new SegmentTree(ua)); left.resize(n); right.resize(n); int l = 0, r = max - min; int result = r; while (l <= r) { int mid = (l + r) >> 1; if (Check(mid)) { result = mid; r = mid - 1; } else { l = mid + 1; } } return result; } private: bool Check(int k) { tree->Clear(); for (int i = n - 1; i >= 0; --i) { right[i] = tree->Get(a[i] - k, a[i] + k, true); if (right[i] == -1) { right[i] = n; } tree->Update(a[i], i); } tree->Clear(); for (int i = 0; i < n; ++i) { left[i] = tree->Get(a[i] - k, a[i] + k, false); tree->Update(a[i], i); } return Check(0, n - 1); } bool Check(int l, int r) { if (r - l + 1 < m) { return false; } int i = l; int j = r; while (i <= j) { if (left[i] < l && right[i] > r) { return Check(l, i - 1) || Check(i + 1, r); } if (left[j] < l && right[j] > r) { return Check(l, j - 1) || Check(j + 1, r); } ++i; --j; } return true; } int n, m; std::vector<int> a; std::vector<int> ua; std::vector<int> left; std::vector<int> right; std::unique_ptr<SegmentTree> tree; };