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;
};