动态查询区间第K大值,单点修改,树状数组套可持久化线段树,线段树中每个代表的相同区间的节点组成了一个树状数组,这样就可以logn的查询前缀和了。
写了好长时间,调了好长时间,毕竟蒟蒻
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 110086
using namespace std;
struct node
{
int l, r, s;
}t[maxn * 30];
int n, m, num, root[maxn], a[maxn >> 1], b[maxn], dat[maxn >> 1][4], size, cnt, lc, rc, ln[maxn], rn[maxn];
void build(int &x, int l, int r)
{
x = ++cnt;
t[x].s = 0;
if (l == r)
return ;
int mid = (l + r) >> 1;
build(t[x].l, l, mid);
build(t[x].r, mid + 1, r);
return ;
}
void update(int &x, int l, int r, int pos, int v)
{
t[++cnt] = t[x];
x = cnt;
t[x].s += v;
if (l == r)
return ;
int mid = (l + r) >> 1;
if (pos <= mid)
update(t[x].l, l, mid, pos, v);
else
update(t[x].r, mid + 1, r, pos, v);
return ;
}
void mutiupdate(int x, int pos, int v)
{
while (x <= n)
{
update(root[x], 1, num, pos, v);
x += x & -x;
}
return ;
}
int query(int k)
{
int l = 1, r = num, tl, tr;
while (l != r)
{
tl = tr = 0;
for (int i = 1; i <= lc; i++)
tl += t[ t[ ln[i] ].l ].s;
for (int i = 1; i <= rc; i++)
tr += t[ t[ rn[i] ].l ].s;
if (tr - tl >= k)
{
for (int i = 1; i <= lc; i++)
ln[i] = t[ ln[i] ].l;
for (int i = 1; i <= rc; i++)
rn[i] = t[ rn[i] ].l;
r = (l + r) >> 1;
}
else
{
for (int i = 1; i <= lc; i++)
ln[i] = t[ ln[i] ].r;
for (int i = 1; i <= rc; i++)
rn[i] = t[ rn[i] ].r;
l = (l + r >> 1) + 1;
k -= tr - tl;
}
}
return l;
}
int getans(int l, int r, int k)
{
lc = rc = 0;
while (l)
{
ln[++lc] = root[l];
l -= l & -l;
}
while (r)
{
rn[++rc] = root[r];
r -= r & -r;
}
return query(k);
}
void solve()
{
sort( b + 1, b + size + 1);
num = unique(b + 1, b + size + 1) - b - 1;
for (int i = 1; i <= n; i++)
a[i] = lower_bound(b + 1, b + num + 1, a[i]) - b;
build(root[0], 1, num);
for (int i = 1; i <= n; i++)
mutiupdate(i, a[i], 1);
for (int i = 1; i <= m; i++)
{
if(dat[i][0] == 0)
printf("%d\n", b[ getans(dat[i][1] - 1, dat[i][2], dat[i][3]) ]);
else
{
int pos = lower_bound(b + 1, b + num + 1, dat[i][2]) - b;
mutiupdate(dat[i][1], a[dat[i][1]], -1);
a[dat[i][1]] = pos;
mutiupdate(dat[i][1], a[dat[i][1]], 1);
}
}
}
int main()
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
b[++size] = a[i];
}
char cmd[3];
for (int i = 1; i <= m; i++)
{
scanf("%s", cmd);
if (cmd[0] == 'C')
{
dat[i][0] = 1;
scanf("%d %d",&dat[i][1], &dat[i][2]);
b[++size] = dat[i][2];
}
else
{
dat[i][0] = 0;
scanf("%d %d %d", &dat[i][1], &dat[i][2], &dat[i][3]);
}
}
solve();
return 0;
}