平衡树
#include <cstdio>
using namespace std;
int root, tot;
struct tree
{
int v, cnt, size, son[2], fa;
void clr() { v = cnt = size = son[0] = son[1] = fa = 0; }
} tr[100010];
bool ident(int x) { return tr[tr[x].fa].son[1] == x; }
void connect(int fa, int x, int how)
{
tr[fa].son[how] = x;
tr[x].fa = fa;
}
int update(int x) { return tr[x].size = tr[x].cnt + tr[tr[x].son[0]].size + tr[tr[x].son[1]].size; }
void rotate(int x)
{
int y = tr[x].fa;
int z = tr[y].fa;
int yson = ident(x);
connect(y, tr[x].son[yson ^ 1], yson);
connect(x, y, yson ^ 1);
tr[x].fa = z;
if (z)
tr[z].son[tr[z].son[1] == y] = x;
update(y);
update(x);
}
void splay(int x)
{
for (int fa; fa = tr[x].fa; rotate(x))
if (tr[fa].fa)
rotate(ident(fa) == ident(x) ? fa : x);
root = x;
}
void insert(int x)
{
if (!root)
{
tr[++tot].fa = 0;
tr[tot].cnt = 1;
tr[tot].v = x;
tr[tot].size = 1;
root = tot;
return;
}
int now = root, fa = 0;
while (1)
{
if (tr[now].v == x)
{
tr[now].cnt++;
tr[now].size++;
splay(now);
return;
}
fa = now;
now = tr[now].son[tr[now].v < x];
if (!now)
{
connect(fa, ++tot, tr[fa].v < x);
tr[tot].cnt = 1;
tr[tot].size = 1;
tr[tot].v = x;
splay(tot);
return;
}
}
}
int findx(int x)
{
int now = root, size = 0;
while (1)
{
if (!now)
return 0;
else if (tr[now].v <= x)
{
size += tr[tr[now].son[0]].size;
if (tr[now].v == x)
{
splay(now);
return size + 1;
}
size += tr[now].cnt;
now = tr[now].son[1];
}
else if (tr[now].v > x)
now = tr[now].son[0];
}
}
int find(int num)
{
int now = root;
while (1)
{
if (num > tr[tr[now].son[0]].size)
{
num -= tr[tr[now].son[0]].size;
if (num <= tr[now].cnt)
{
splay(now);
return tr[now].v;
}
num -= tr[now].cnt;
now = tr[now].son[1];
}
else
now = tr[now].son[0];
}
}
int qq()
{
int now = tr[root].son[0];
while (tr[now].son[1])
now = tr[now].son[1];
return now;
}
int hj()
{
int now = tr[root].son[1];
while (tr[now].son[0])
now = tr[now].son[0];
return now;
}
void del(int x)
{
if (!findx(x))
return;
int now = root, son;
if (tr[now].cnt > 1)
{
tr[now].cnt--;
tr[now].size--;
return;
}
if (!tr[now].son[1])
{
root = tr[now].son[0];
tr[root].fa = 0;
tr[now].clr();
return;
}
if (!tr[now].son[0])
{
root = tr[now].son[1];
tr[root].fa = 0;
tr[now].clr();
return;
}
splay(qq());
connect(root, tr[now].son[1], 1);
tr[now].clr();
update(root);
}
int main()
{
int n;
scanf("%d", &n);
while (n--)
{
int opt, x;
scanf("%d%d", &opt, &x);
if (opt == 1)
insert(x); //插入一个元素
if (opt == 2)
del(x); //删除一个元素
if (opt == 3)
printf("%d\n", findx(x)); //查询x的排名
if (opt == 4)
printf("%d\n", find(x)); //查询排名为x的数
if (opt == 5)
{
insert(x), printf("%d\n", tr[qq()].v), del(x);
} //求小于x且最大的数
if (opt == 6)
{
insert(x), printf("%d\n", tr[hj()].v), del(x);
} //求大于x且最小的数
}
}
可持久化线段树
void update(ll l, ll r, ll &now, ll p, ll c)
{
if (!p)
return;
if (!now)
now = ++cnt;
sum[now] += c;
if (l == r)
return;
ll m = (l + r) >> 1;
if (p <= m)
update(lson, p, c);
else
update(rson, p, c);
}
ll query(ll l, ll r, ll now, ll a, ll b)//查询权值在[a,b]范围内个数
{
if (!now)
return 0;
if (l >= a && r <= b)
return sum[now];
ll m = l + r >> 1, ans = 0;
if (a <= m)
ans = query(lson, a, b);
if (b > m)
ans += query(rson, a, b);
return ans;
}
主席树求区间第k大
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 60006
int a[N], b[N], R[N], T[N], n, tot;
int Ro[N], Lo[N], rn;
struct Q
{
char o;
int i, j, k;
}q[N/6];
struct Tr
{
int ls, rs, c;
}tr[N*40];
int build(int l, int r)
{
int mid = l+r>>1, root = tot++;
tr[root].c = 0;
if (l < r)
{
tr[root].ls = build(l, mid);
tr[root].rs = build(mid+1, r);
}
return root;
}
void init(int r)
{
tot = 0;
memset(R, 0, sizeof(R));
T[0] = build(1, r);
}
int lb(int k) {return k&(-k);}
int update(int l, int r, int val, int root, int ad)
{
int nr = tot++, mid = l+r>>1;
tr[nr].c = tr[root].c+ad;
if (l == r) return nr;
if (val <= mid)
{
tr[nr].ls = update(l, mid, val, tr[root].ls, ad);
tr[nr].rs = tr[root].rs;
}
else
{
tr[nr].rs = update(mid+1, r, val, tr[root].rs, ad);
tr[nr].ls = tr[root].ls;
}
return nr;
}
void add(int i, int k, int r, int ad)
{
int v = lower_bound(b+1, b+r+1, k)-b;
while (i <= rn)
{
R[i] = update(1, r, v, R[i], ad);
i += lb(i);
}
}
void go(int root[], int d)
{
int i;
for (i = 1;i <= root[0];i++)
root[i] = d?tr[root[i]].rs:tr[root[i]].ls;
}
int query(int l, int r, int k, int Rroot, int Lroot)
{
if (l == r) return l;
int i, Rls = 0, Lls = 0, mid = l+r>>1;
int sum = tr[tr[Rroot].ls].c-tr[tr[Lroot].ls].c;
for (i = 1;i <= Ro[0];i++) Rls += tr[tr[Ro[i]].ls].c;
for (i = 1;i <= Lo[0];i++) Lls += tr[tr[Lo[i]].ls].c;
if (k <= Rls-Lls+sum)
{
go(Ro, 0), go(Lo, 0);
return query(l, mid, k, tr[Rroot].ls, tr[Lroot].ls);
}
else
{
go(Ro, 1), go(Lo, 1);
return query(mid+1, r, k+Lls-Rls-sum, tr[Rroot].rs, tr[Lroot].rs);
}
}
void cal(int i, int j, int k, int r)
{
Ro[0] = Lo[0] = 0;
int ti = j;
while (ti > 0)
{
Ro[++Ro[0]] = R[ti];
ti -= lb(ti);
}
ti = i;
while (ti > 0)
{
Lo[++Lo[0]] = R[ti];
ti -= lb(ti);
}
printf("%d\n", b[query(1, r, k, T[j], T[i])]);
}
int main()
{
int ca, m, i, j, k;
scanf("%d", &ca);
while (ca--)
{
scanf("%d%d", &n, &m);
rn = n;
for (i = 1;i <= n;i++)
{
scanf("%d", &a[i]);
b[i] = a[i];
}
for (i = 0;i < m;i++)
{
scanf(" %c", &q[i].o);
if (q[i].o == 'Q') scanf("%d%d%d", &q[i].i, &q[i].j, &q[i].k);
else scanf("%d%d", &q[i].i, &q[i].j), b[++n] = q[i].j;
}
sort(b+1, b+1+n);
int r = unique(b+1, b+1+n)-b-1;
init(r);
for (i = 1;i <= rn;i++) T[i] = update(1, r, lower_bound(b+1, b+1+r, a[i])-b, T[i-1], 1);
for (i = 0;i < m;i++)
{
if (q[i].o == 'Q') cal(q[i].i-1, q[i].j, q[i].k, r);
else
{
add(q[i].i, a[q[i].i], r, -1), add(q[i].i, q[i].j, r, 1);
a[q[i].i] = q[i].j;
}
}
}
}