Loading

K大树

权值线段树套线段树

之前没有做过权值线段树套外层树,也是第一次写动态开点的完整线段树

push_down 的时候要动态开点。其实跟普通线段树是一样的。

写之前一定要先想清楚。外层的线段树是将值离散化后建的,外层的线段树可以用 o<<1o<<1|1 , 这样进行转移。内层的线段树需要动态开点,所以需要数组 lc[N] , rc[N]

要计算开的空间大小。

/*
 * @Author: zhl
 * @Date: 2020-11-17 13:55:59
 */
#include<bits/stdc++.h>
#define mid (l + r >> 1)
#define lo (o << 1)
#define ro (o << 1 | 1)
using ll = long long;
using namespace std;

const int N = 5e4 + 10, P = N * 17 * 17, M = 4 * N;
int n, m;

int root[M], lc[P], rc[P], lz[P], tot;
ll sum[P];

void push_down(int u,int l,int r) {
	if (!lc[u])lc[u] = ++tot;
	lz[lc[u]] += lz[u];
	if (!rc[u])rc[u] = ++tot;
	lz[rc[u]] += lz[u];

	sum[lc[u]] += (mid - l + 1) * lz[u];
	sum[rc[u]] += (r - mid) * lz[u];

	lz[u] = 0;
}
void updt(int& rt, int L,int R, int o = 1, int l = 1, int r = n) {
	if (!rt) rt = ++tot;
	if (L <= l and r <= R) {
		lz[rt] ++;
		//sum[rt] += R - L + 1;//我是傻逼草
		sum[rt] += r - l + 1;
		return;
	}
	if (lz[rt])push_down(rt, l , r);
	if (L <= mid)updt(lc[rt], L, R, lo, l, mid);
	if (R > mid)updt(rc[rt], L, R, ro, mid + 1, r);
	sum[rt] = sum[lc[rt]] + sum[rc[rt]];
}

ll query(int rt, int L, int R, int o = 1, int l = 1, int r = n) {
	if (!rt)return 0;
	if (L <= l and r <= R) {
		return sum[rt];
	}
	if (lz[rt])push_down(rt, l, r);
	ll ans = 0;
	if (L <= mid)ans += query(lc[rt], L, R, lo, l, mid);
	if (R > mid) ans += query(rc[rt], L, R, ro, mid + 1, r);
	return ans;
}


int cntID, id[N];

void add(int L,int R, int pos, int o = 1, int l = 1, int r = cntID) {
	updt(root[o], L, R);
	if (l == r)return;
	if (pos <= mid)add(L, R, pos, lo, l, mid);
	else add(L, R, pos, ro, mid + 1, r);
}

int get_kth(int L,int R,ll k,int o = 1, int l = 1, int r = cntID) {
	if (l == r)return id[l];
	
	ll num = query(root[ro], L, R);
	if (num >= k) return get_kth(L, R, k, ro, mid + 1, r);
	else return get_kth(L, R, k - num, lo, l, mid);
}


struct {
	int op, a, b, c;
}q[N];

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++) {
		scanf("%d%d%d%d", &q[i].op, &q[i].a, &q[i].b, &q[i].c);
		if (q[i].op == 1) {
			id[++cntID] = q[i].c;
		}
	}
	sort(id + 1, id + 1 + cntID);
	cntID = unique(id + 1, id + 1 + cntID) - id - 1;

	for (int i = 1; i <= m; i++) {
		if (q[i].op == 1)q[i].c = lower_bound(id + 1, id + 1 + cntID, q[i].c) - id;
	}

	for (int i = 1; i <= m; i++) {
		if (q[i].op == 1) {
			add(q[i].a, q[i].b, q[i].c);
		}
		else {
			printf("%d\n", get_kth(q[i].a, q[i].b, q[i].c));
		}
	}
}
posted @ 2020-11-17 14:32  —O0oO-  阅读(106)  评论(0编辑  收藏  举报