每天有10亿人的登录,用户登出时,会输出登入时间和登出时间,平均在线时长为1小时,如何快速的求某一秒钟内的在线人数。
思路:可以用线段树来处理。在知道(loginTime,logoutTime)时,将区间(loginTime, logoutTime-1)加1。
具体的线段树代码 如下:
#pragma once const int N = 2 * 24 * 3600; #define LSON(o) (o << 1) #define RSON(o) ((o << 1) + 1) class Node { public: void setNode(int l, int r, int add, int sum) { this->l = l; this->r = r; this->add = add; this->sum = sum; } private: friend class RMQ; int l, r; int add; int sum; }; Node node[N]; class RMQ { public: RMQ() { tree = node; } void build(int o, int left, int right) { if (left == right) { tree[o].setNode(left, right, 0, 0); } else { int mid = (left + right) >> 1; build(o * 2, left, mid); build(o * 2 + 1, mid + 1, right); tree[o].l = left; tree[o].r = right; tree[o].add = 0; tree[o].sum = 0; } } void update(int o, int left, int right, int v) { if (left <= tree[o].l && right >= tree[o].r) { tree[o].add += v; } else { int mid = (tree[o].l + tree[o].r) >> 1; if (left <= mid) update(LSON(o), left, right, v); if (right > mid) update(RSON(o), left, right, v); } maintain(o); } int query(int o, int left, int right, int add) { if (left <= tree[o].l && right >= tree[o].r) { return tree[o].sum + add * (tree[o].r - tree[o].l + 1); } else { int mid = (tree[o].l + tree[o].r) >> 1; int result = 0; if (left <= mid) { result += query(LSON(o), left, right, add + tree[o].add); } if (right > mid) { result += query(RSON(o), left, right, add + tree[o].add); } return result; } } private: void pushdown(int o) { if (tree[o].add > 0) { tree[LSON(o)].add += tree[o].add; tree[RSON(o)].add += tree[o].add; tree[o].add = 0; } } void maintain(int o) { if (tree[o].r > tree[o].l) { tree[o].sum = tree[LSON(o)].sum + tree[RSON(o)].sum; } tree[o].sum += tree[o].add * (tree[o].r - tree[o].l + 1); } Node* tree; };