您的位置:首页 > 其它

bzoj3110: [Zjoi2013]K大数查询 【cdq分治&树套树】

2015-12-23 12:40 381 查看
  模板题,折腾了许久。

  cqd分治整体二分,感觉像是把询问分到答案上。

#include <bits/stdc++.h>
#define rep(i, a, b) for (register int i = a; i <= b; i++)
#define drep(i, a, b) for (register int i = a; i >= b; i--)
#define REP(i, a, b) for (register int i = a; i < b; i++)
#define pb push_back
#define mp make_pair
#define clr(x) memset(x, 0, sizeof(x))
#define xx first
#define yy second
using namespace std;
typedef long long i64;
typedef pair<int, int> pii;
const int inf = ~0U >> 1;
const i64 INF = ~0ULL >> 1;
//*******************************

const int maxn = 200005, maxnn = 20000005;

int root[maxn << 2];
int ls[maxnn], rs[maxnn], sum[maxnn], lazy[maxnn];

int ndtot, n, N;
inline void Push_up(int o) { sum[o] = sum[ls[o]] + sum[rs[o]]; }
inline void Push_down(int o, int m) {
if (!lazy[o]) return;
if (!ls[o]) ls[o] = ++ndtot;
if (!rs[o]) rs[o] = ++ndtot;
lazy[ls[o]] += lazy[o], lazy[rs[o]] += lazy[o];
sum[ls[o]] += lazy[o] * (m - (m >> 1)), sum[rs[o]] += lazy[o] * (m >> 1);
lazy[o] = 0;
}
void update(int &k, int l, int r, int ql, int qr, int v) {
if (!k) k = ++ndtot;
if (ql <= l && r <= qr) {
sum[k] += v * (r - l + 1);
lazy[k] += v;
return;
}
int mid = l + r >> 1;
Push_down(k, r - l + 1);
if (ql <= mid) update(ls[k], l, mid, ql, qr, v);
if (qr > mid) update(rs[k], mid + 1, r, ql, qr, v);
Push_up(k);
}
void insrt(int o, int l, int r, int ql, int qr, int c) {
while (l != r) {
int mid = l + r >> 1;
update(root[o], 1, n, ql, qr, 1);
if (c <= mid) o <<= 1, r = mid;
else o = o << 1 | 1, l = mid + 1;
}
update(root[o], 1, n, ql, qr, 1);
}

int query(int o, int l, int r, int ql, int qr) {
if (!o) return 0;
if (ql <= l && r <= qr) return sum[o];
Push_down(o, r - l + 1);
int mid = l + r >> 1;
int ret(0);
if (ql <= mid) ret += query(ls[o], l, mid, ql, qr);
if (qr > mid) ret += query(rs[o], mid + 1, r, ql, qr);
return ret;
}
int solve(int o, int l, int r, int ql, int qr, int c) {
while (l != r) {
int mid = l + r >> 1;
int t = query(root[o << 1 | 1], 1, n, ql, qr);
if (t >= c) l = mid + 1, o = o << 1 |1;
else r = mid, o = o << 1, c -= t;
}
return l;
}

int main() {
int m; scanf("%d%d", &n, &m);
N = 2 * n + 1;
while (m--) {
int flag, a, b, c; scanf("%d%d%d%d", &flag, &a, &b, &c);
if (flag == 1) {
c += n + 1;
insrt(1, 1, N, a, b, c);
}
else printf("%d\n", solve(1, 1, N, a, b, c) - n - 1);
}
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: