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;
};
posted @ 2017-04-14 21:31  朝拜明天19891101  阅读(265)  评论(0编辑  收藏  举报