二分 + 线段树 区间更新(模板)

序列维护

http://www.nowcoder.com/questionTerminal/8f5759df4aaf40a28906dfedf28fbf6d

#include <bits/stdc++.h>

using namespace std;

class segtree{
public:
  int n;
  int* data;
  int* tree;
  int* lazy;

  segtree(int* arr, int _n) : n(_n) {
    data = new int[_n];
    tree = new int[_n * 4];
    lazy = new int[_n * 4];
    fill_n(tree, _n * 4, 0);
    fill_n(lazy, _n * 4, 0);
    for (int i = 0; i < _n; i++) {
      data[i] = arr[i];
    }
    build(0, 0, n - 1);
  }

  ~segtree() {
    delete []data;
    delete []tree;
    delete []lazy;
  }

  void push(int tId) {
    tree[tId] = tree[tId * 2 + 1] + tree[tId * 2 + 2];
  }

  void pull(int tId, int l, int r) {
    int mid = (l + r) / 2;
    tree[tId * 2 + 1] += (mid - l + 1) * lazy[tId];
    tree[tId * 2 + 2] += (r - mid) * lazy[tId];
    lazy[tId * 2 + 1] += lazy[tId];
    lazy[tId * 2 + 2] += lazy[tId];
    lazy[tId] = 0;
  }

  void build(int tId, int l, int r) {
    if (l == r) {
      tree[tId] = data[l];
      return;
    }
    int mid = (l + r) / 2;
    build(tId * 2 + 1, l, mid);
    build(tId * 2 + 2, mid + 1, r);
    push(tId);
  }

  int get(int tId, int l, int r, int x) {
    if (l == r && l == x) {
      return tree[tId];
    }
    if (lazy[tId]) {
      pull(tId, l, r);
    }
    int mid = (l + r) / 2;
    if (x <= mid) {
      return get(tId * 2 + 1, l, mid, x);
    } else {
      return get(tId * 2 + 2, mid + 1, r, x);
    }
  }

  void modify(int tId, int l, int r, int ml, int mr, int v) {
    if (ml <= l && r <= mr) {
      tree[tId] += (r - l + 1) * v;
      lazy[tId] += v;
      return;
    }
    if (lazy[tId] != 0) {
      pull(tId, l, r);
    }
    int mid = (l + r) >> 1;
    if (mr <= mid) {
      modify((tId * 2) + 1, l, mid, ml, mr, v);
    } else if (ml > mid) {
      modify((tId * 2) + 2, mid + 1, r, ml, mr, v);
    } else {
      modify((tId * 2) + 1, l, mid, ml, mid, v);
      modify((tId * 2) + 2, mid + 1, r, mid + 1, mr, v);
    }
    push(tId);
  }
};

int arr[234567];

int main() {
  int n, q;
  cin >> n >> q;
  for (int i = 0; i < n; i++) {
    scanf("%d", &arr[i]);
  }
  sort(arr, arr + n);
  segtree st(arr, n);
  while (q--) {
    int x;
    int l = 0, r = n - 1;
    scanf("%d", &x);
    while (l <= r) {
      int mid = (l + r) >> 1;
      if (st.get(0, 0, n - 1, mid) < x) l = mid + 1;
      else r = mid - 1;
    }
    if (l >= n) {
      cout << "0" << "\n";
    } else {
      cout << n - 1 - l + 1 << "\n";
      st.modify(0, 0, n - 1, l, n - 1, -1);
    }
  }
  return 0;
}
全部评论

相关推荐

头像
05-12 09:14
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务