QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#61320#2555. Two Bulletsalpha1022WA 2ms3664kbC++145.0kb2022-11-12 09:53:112022-11-12 09:53:14

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2022-11-12 09:53:14]
  • 评测
  • 测评结果:WA
  • 用时:2ms
  • 内存:3664kb
  • [2022-11-12 09:53:11]
  • 提交

answer

#include <bits/stdc++.h>

using namespace std;

const int inf = 0x3f3f3f3f;

const int N = 1e5;

int n, p[N + 5], q[N + 5];
int level[N + 5];
int a[N + 5], b[N + 5];

struct BinaryIndexedTree {
  int c[N + 5];
  void update(int x, int k) {
    for (; x <= n; x += x & -x) c[x] = max(c[x], k);
  }
  int query(int x) {
    int ret = 0;
    for (; x; x &= x - 1) ret = max(ret, c[x]);
    return ret;
  }
} bit;

struct TreeOfTree {
  struct segnode {
    int max;
    int ls, rs;
  } seg[N * 700 + 5];
  void insert(int x, int k, int &u, int tl, int tr) {
    static int tot = 0;
    if (!u) u = ++tot;
    seg[u].max = max(seg[u].max, k);
    if (tl == tr) return ;
    int mid = (tl + tr) >> 1;
    if (x <= mid) insert(x, k, seg[u].ls, tl, mid);
    else insert(x, k, seg[u].rs, mid + 1, tr);
  }
  int query(int l, int r, int u, int tl, int tr) {
    if (!u || (l <= tl && tr <= r)) return seg[u].max;
    int mid = (tl + tr) >> 1;
    int ret = 0;
    if (l <= mid) ret = max(ret, query(l, r, seg[u].ls, tl, mid));
    if (r > mid) ret = max(ret, query(l, r, seg[u].rs, mid + 1, tr));
    return ret;
  }
  #define ls (u << 1)
  #define rs (ls | 1)
  int rt[N * 4 + 5];
  void insert(int x, int y, int k, int u, int tl, int tr) {
    insert(y, k, rt[u], 1, n);
    if (tl == tr) return ;
    int mid = (tl + tr) >> 1;
    if (x <= mid) insert(x, y, k, ls, tl, mid);
    else insert(x, y, k, rs, mid + 1, tr);
  }
  void insert(int x, int y, int k) { insert(x, y, k, 1, 1, n); }
  int query(int l, int r, int x, int y, int u, int tl, int tr) {
    if (l <= tl && tr <= r) return query(x, y, rt[u], 1, n);
    int mid = (tl + tr) >> 1;
    int ret = 0;
    if (l <= mid) ret = max(ret, query(l, r, x, y, ls, tl, mid));
    if (r > mid) ret = max(ret, query(l, r, x, y, rs, mid + 1, tr));
    return ret;
  }
  int query(int l, int r, int x, int y) { return l <= r && x <= y ? query(l, r, x, y, 1, 1, n) : 0; }
  #undef ls
  #undef rs
} tr;

struct SegmentTree {
  #define ls (u << 1)
  #define rs (ls | 1)
  struct node {
    int min;
    bool vis;
  } seg[N * 4 + 5];
  void build(int u, int tl, int tr) {
    if (tl == tr) { seg[u].min = p[tl]; return ; }
    int mid = (tl + tr) >> 1;
    build(ls, tl, mid), build(rs, mid + 1, tr);
    seg[u].min = min(seg[ls].min, seg[rs].min);
  }
  void build() { build(1, 1, n); }
  int prev(int x, int u, int tl, int tr) {
    if (seg[u].min >= p[x]) return 0;
    if (tl == tr) return tl;
    int mid = (tl + tr) >> 1;
    if (x <= mid) return prev(x, ls, tl, mid);
    int ret = prev(x, rs, mid + 1, tr);
    if (!ret) ret = prev(x, ls, tl, mid);
    return ret;
  }
  int prev(int x) { return prev(x, 1, 1, n); }
  void undo(int l, int r, int u, int tl, int tr) {
    seg[u].vis = 0;
    if (l <= tl && tr <= r) return ;
    int mid = (tl + tr) >> 1;
    if (l <= mid) undo(l, r, ls, tl, mid);
    if (r > mid) undo(l, r, rs, mid + 1, tr);
  }
  void undo(int l, int r) { undo(l, r, 1, 1, n); }
  void erase(int x, int u, int tl, int tr) {
    if (tl == tr) { seg[u].min = inf; return ; }
    int mid = (tl + tr) >> 1;
    if (x <= mid) erase(x, ls, tl, mid);
    else erase(x, rs, mid + 1, tr);
    seg[u].min = min(seg[ls].min, seg[rs].min);
  }
  void erase(int x) {
    int y = prev(x, 1, 1, n);
    undo(y + 1, x, 1, 1, n), erase(x, 1, 1, n);
  }
  void search(vector<int> &ret, bool flag, int rmin, int u, int tl, int tr) {
    if (seg[u].min >= rmin || seg[u].vis) return ;
    flag &= seg[u].vis, seg[u].vis = 1;
    if (tl == tr) { ret.push_back(tl); return ; }
    int mid = (tl + tr) >> 1;
    search(ret, flag, rmin, rs, mid + 1, tr);
    search(ret, flag, min(rmin, seg[rs].min), ls, tl, mid);
  }
  vector<int> search() {
    vector<int> ret;
    search(ret, 1, inf, 1, 1, n);
    return ret;
  }
  #undef ls
  #undef rs
} seg;

vector<pair<int, int>> ans;
priority_queue<int> que;

int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; ++i) scanf("%d", p + i), q[p[i]] = i;
  for (int i = n; i; --i)
    bit.update(p[i], (level[i] = bit.query(p[i] - 1)) + 1);
  iota(a + 1, a + n + 1, 1), sort(a + 1, a + n + 1, [](int x, int y) { return level[x] > level[y]; });
  for (int l = 1, r; l <= n; l = r + 1) {
    for (r = l; r < n && level[a[r + 1]] == level[a[l]]; ++r);
    sort(a + l, a + r + 1, [](int x, int y) {
      bool flag = 0;
      if (x > y) flag = 1, swap(x, y);
      return (tr.query(1, x - 1, p[x] + 1, p[y]) < tr.query(x + 1, y - 1, p[y] + 1, n)) ^ flag;
    });
    for (int i = l; i <= r; ++i) tr.insert(a[i], p[a[i]], i);
  }
  for (int i = 1; i <= n; ++i) b[a[i]] = i;
  seg.build();
  for (;;) {
    auto res = seg.search();
    for (int i: res) que.push(b[i]);
    if (que.empty()) break;
    int x = que.top(); que.pop(), seg.erase(a[x]);
    int y = x;
    if (!que.empty()) y = que.top(), que.pop(), seg.erase(a[y]);
    ans.emplace_back(p[a[x]], p[a[y]]);
  }
  reverse(ans.begin(), ans.end());
  printf("%d\n", ans.size());
  for (auto i: ans) printf("%d %d\n", i.first, i.second);
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 2ms
memory: 3664kb

input:

8
4 3 8 2 1 7 6 5

output:

4
4 4
3 3
2 2
1 5

result:

FAIL removed all buildings