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

序列维护

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;
}
全部评论

相关推荐

兄弟们,绩效自评一定得给自己打A啊!千万别谦虚给低分,不然领导正愁给谁高分,你这不就“主动请缨”了嘛,而且多数领导不会给你更高分。我几年前试用期绩效自评打了B,领导就给了同等级,还好是试用期。真别等领导主动给高评价!
准备进厂的劳伦斯很迷人:小学时候有个册子 自评 小组 老师 我谦虚打了个b 小组别人给我打b 老师来句我觉得能给他打a 但是小组长说他自评是b怎么能打高呢 那时候我才明白的道理
点赞 评论 收藏
分享
01-14 12:08
门头沟学院 Java
神哥了不得:(非引流)1.既然发出来了简历,就稍微提一点点小建议,确实简历很不错了,练手项目可以换一些质量高的,工作内容,可以加上一些量化指标,比如第一条系统响应速度由多少变成多少,减少了百分之多少,第4条就很不错。2.广投,年前实习招募比较少了
点赞 评论 收藏
分享
Cassifa:发的字比你都多的一律视为骗子或者想白嫖压榨实习生的
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务