树状数组套线段树

1.P3380 【模板】二逼平衡树(树套树)

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 5e4 + 5;
const int mn = - 1e8 - 5;
const int mx = 1e8 + 5;
int n, m, a[N], cnt, rt[N], L, R, nl[N], nr[N];
struct node{int ls, rs, val;}tr[N * 200];
inline int read()
{
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
int lowbit(int x) {return x & (- x);}
void insert(int &k, int l, int r, int pos, int val)
{
	if(!k) k = ++ cnt; tr[k].val += val;
	if(l == r) return; int mid = (l + r) >> 1;
	if(pos <= mid) insert(tr[k].ls, l, mid, pos, val);
	else insert(tr[k].rs, mid + 1, r, pos, val);
}
void get(int l, int r)
{
	L = R = 0;
	for(int i = l; i; i -= lowbit(i)) nl[++ L] = rt[i];
	for(int i = r; i; i -= lowbit(i)) nr[++ R] = rt[i];
}
int get_rank(int l, int r, int k)
{
	if(l == r) return 1; int mid = (l + r) >> 1, now = 0;
	for(int i = 1; i <= L; i ++) now -= tr[tr[nl[i]].ls].val;
	for(int i = 1; i <= R; i ++) now += tr[tr[nr[i]].ls].val;
	if(k <= mid)
	{
		for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].ls;
		for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].ls;
		return get_rank(l, mid, k);
	}
	else
	{
		for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].rs;
		for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].rs;
		return now + get_rank(mid + 1, r, k);
	}
}
int get_num(int l, int r, int k)
{
	if(l == r) return l; int mid = (l + r) >> 1, now = 0;
	for(int i = 1; i <= L; i ++) now -= tr[tr[nl[i]].ls].val;
	for(int i = 1; i <= R; i ++) now += tr[tr[nr[i]].ls].val;
	if(now >= k)
	{
		for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].ls;
		for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].ls;
		return get_num(l, mid, k);
	}
	else
	{
		for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].rs;
		for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].rs;
		return get_num(mid + 1, r, k - now);
	}
}
int main()
{
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	n = read(); m = read();
	for(int i = 1; i <= n; i ++)
	{
		a[i] = read();
		for(int j = i; j <= n; j += lowbit(j)) insert(rt[j], mn, mx, a[i], 1);
	}
	int opt, l, r, x, k, y;
	while(m -- > 0)
	{
		opt = read();
		if(opt == 1) {l = read(); r = read(); k = read(); get(l - 1, r); printf("%d
", get_rank(mn, mx, k));}
		else if(opt == 2) {l = read(); r = read(); k = read(); get(l - 1, r); printf("%d
", get_num(mn, mx, k));}
		else if(opt == 3)
		{
			x = read(); y = read();
			for(int j = x; j <= n; j += lowbit(j)) insert(rt[j], mn, mx, a[x], -1);
			a[x] = y;
			for(int j = x; j <= n; j += lowbit(j)) insert(rt[j], mn, mx, a[x], 1);
		}
		else if(opt == 4)
		{
			l = read(); r = read(); k = read();
			get(l - 1, r); int em = get_rank(mn, mx, k); get(l - 1, r);
			printf("%d
", em == 1 ? -2147483647 : get_num(mn, mx, em - 1));
		}
		else if(opt == 5)
		{
			l = read(); r = read(); k = read();
			get(l - 1, r); int em = get_rank(mn, mx, k + 1);
			get(l - 1, r); int ans = get_num(mn, mx, em);
			printf("%d
", ans == mx ? 2147483647 : ans);
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

2.P2617 Dynamic Rankings

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e5 + 5;
const int mx = 1e9 + 5;
int n, m, rt[N], a[N], cnt, nl[N], nr[N], L, R;
char s[5];
struct node{int ls, rs, siz;}tr[N * 300];
inline int read()
{
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
int lowbit(int x) {return x & (- x);}
void add(int &k, int l, int r, int pos, int val)
{
	if(!k) k = ++ cnt;
	tr[k].siz += val;
	if(l == r) return;
	int mid = (l + r) >> 1;
	if(pos <= mid) add(tr[k].ls, l, mid, pos, val);
	else add(tr[k].rs, mid + 1, r, pos, val);
}
void get(int l, int r)
{
	L = R = 0;
	for(int i = l; i; i -= lowbit(i)) nl[++ L] = rt[i];
	for(int i = r; i; i -= lowbit(i)) nr[++ R] = rt[i];
}
int get_num(int l, int r, int k)
{
	if(l == r) return l;
	int mid = (l + r) >> 1, sizls = 0;
	for(int i = 1; i <= L; i ++) sizls -= tr[tr[nl[i]].ls].siz;
	for(int i = 1; i <= R; i ++) sizls += tr[tr[nr[i]].ls].siz;
	if(sizls >= k)
	{
		for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].ls;
		for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].ls;
		return get_num(l, mid, k);
	}
	else
	{
		for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].rs;
		for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].rs;
		return get_num(mid + 1, r, k - sizls);
	}
}
void work()
{
	n = read(); m = read();
	for(int i = 1; i <= n; i ++)
	{
		a[i] = read();
		for(int j = i; j <= n; j += lowbit(j)) add(rt[j], 0, mx, a[i], 1);
	}
	for(int i = 1, x, y, k; i <= m; i ++)
	{
		scanf("%s", s); x = read(); y = read();
		if(s[0] == 'Q')
		{
			k = read(); get(x - 1, y);
			printf("%d
", get_num(0, mx, k));
		}
		else
		{
			for(int j = x; j <= n; j += lowbit(j)) add(rt[j], 0, mx, a[x], -1);
			a[x] = y;
			for(int j = x; j <= n; j += lowbit(j)) add(rt[j], 0, mx, a[x], 1);
		}
	}
}
int main() {return work(), 0; }

3.P3157 [CQOI2011]动态逆序对

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
const int N = 100005;
int n, m, a[N], rt[N], cnt, L, R, nl[N], nr[N], po[N];
ll ans;
struct node{int ls, rs; int siz;}tr[N * 200];
inline int read()
{
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-')f = -1; ch = getchar(); }
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
	return x * f;
}
int lowbit(int x) {return x & (- x);}
void add(int &x, int l, int r, int pos, int val)
{
	if(!x) x = ++ cnt;
	tr[x].siz += val;
	if(l == r) return;
	int mid = (l + r) >> 1;
	if(pos <= mid) add(tr[x].ls, l, mid, pos, val);
	else add(tr[x].rs, mid + 1, r, pos, val);
}
void get(int l, int r)
{
	L = R = 0;
	for(int i = l; i; i -= lowbit(i)) nl[++ L] = rt[i];
	for(int i = r; i; i -= lowbit(i)) nr[++ R] = rt[i];
}
int query(int l, int r, int val)
{
	int mid = (l + r) >> 1, sizls = 0;
	if(l == r) return 0;
	for(int i = 1; i <= L; i ++) sizls -= tr[tr[nl[i]].ls].siz;
	for(int i = 1; i <= R; i ++) sizls += tr[tr[nr[i]].ls].siz;
	if(val <= mid)
	{
		for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].ls;
		for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].ls;
		return query(l, mid, val);
	}
	else
	{
		for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].rs;
		for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].rs;
		return sizls + query(mid + 1, r, val);
	}
}
int ask(int l, int r, int val)
{
	int mid = (l + r) >> 1, sizls = 0;
	if(l == r) return 0;
	for(int i = 1; i <= L; i ++) sizls -= tr[tr[nl[i]].rs].siz;
	for(int i = 1; i <= R; i ++) sizls += tr[tr[nr[i]].rs].siz;
	if(val <= mid)
	{
		for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].ls;
		for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].ls;
		return sizls + ask(l, mid, val);
	}
	else
	{
		for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].rs;
		for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].rs;
		return ask(mid + 1, r, val);
	}
}
void work()
{
	n = read(); m = read();
	for(int i = 1; i <= n; i ++)
	{
		a[i] = read(); po[a[i]] = i; get(0, i); ans += ask(1, n, a[i]);
		for(int j = i; j <= n; j += lowbit(j)) add(rt[j], 1, n, a[i], 1);
		//在插入之前直接统计就好 ,不用再循环一遍 
	}
	for(int i = 1, x; i <= m; i ++)
	{
		x = read();
		printf("%lld
", ans);
		get(po[x], n); ans -= query(1, n, x);
		get(0, po[x] - 1); ans -= ask(1, n, x);
		for(int j = po[x]; j <= n; j += lowbit(j)) add(rt[j], 1, n, x, -1);
	}
}
int main() {return work(), 0; }
原文地址:https://www.cnblogs.com/Sunny-r/p/15031791.html