动态求区间第K大,有修改操作,用树状数组求和,此外在ZOJ可能会超内存,参考了
kuangbin巨巨,建树和修改分开来操作,建树用静态前缀和,修改用树状数组,每次求和2部分相加。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 60010;
const int maxm = 2500010;
int ls[maxm], rs[maxm], c[maxm];
int T[maxn], S[maxn], tot, m;
int num[maxn], a[maxn], use[maxn], n, q;
struct node
{
int kind, l, r, k;
}Q[maxn];
void build(int l, int r, int& rt)
{
rt = ++tot;
c[rt] = 0;
if(l == r)
return;
int m = l+r>>1;
build(l, m, ls[rt]);
build(m+1, r, rs[rt]);
}
void update(int last, int p, int l, int r, int& rt, int val)
{
rt = ++tot;
ls[rt] = ls[last];
rs[rt] = rs[last];
c[rt] = c[last]+val;
if(l == r)
return;
int m = (l+r)>>1;
if(p <= m)
update(ls[last], p, l, m, ls[rt], val);
else
update(rs[last], p, m+1, r, rs[rt], val);
}
int lowbit(int x)
{
return x & -x;
}
int sum(int x)
{
int ans = 0;
while(x > 0)
{
ans += c[ls[use[x]]];
x -= lowbit(x);
}
return ans;
}
int query(int x, int y, int k)
{
int left = T[x-1], right = T[y];
int l = 0, r = m-1;
for(int i = x-1; i > 0; i -= lowbit(i))
use[i] = S[i];
for(int i = y; i > 0; i -= lowbit(i))
use[i] = S[i];
while(l < r)
{
int mid = (l+r) >> 1;
int tmp = sum(y) - sum(x-1) + c[ls[right]] - c[ls[left]];
if(tmp >= k)
{
r = mid;
for(int i = x-1; i > 0; i -= lowbit(i))
use[i] = ls[use[i]];
for(int i = y; i > 0; i -= lowbit(i))
use[i] = ls[use[i]];
left = ls[left];
right = ls[right];
}
else
{
l = mid+1;
k -= tmp;
for(int i = x-1; i > 0; i -= lowbit(i))
use[i] = rs[use[i]];
for(int i = y; i > 0; i -= lowbit(i))
use[i] = rs[use[i]];
left = rs[left];
right = rs[right];
}
}
return l;
}
void init()
{
sort(num, num+m);
int cnt = unique(num, num+m)-num;
m = cnt;
}
void update2(int x, int p, int val)
{
while(x <= n)
{
update(S[x], p, 0, m-1, S[x], val);
x += lowbit(x);
}
}
int getId(int x)
{
return lower_bound(num, num+m, x)-num;
}
void cal()
{
tot = 0;
m = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
num[m++] = a[i];
}
for(int i = 0; i < q; i++)
{
char s[10];
scanf("%s", s);
if(s[0] == 'Q')
{
Q[i].kind = 0;
scanf("%d %d %d", &Q[i].l, &Q[i].r, &Q[i].k);
}
else
{
Q[i].kind = 1;
scanf("%d %d", &Q[i].l, &Q[i].r);
num[m++] = Q[i].r;
}
}
init();
build(0, m-1, T[0]);
for(int i = 1; i <= n; i++)
{
update(T[i-1], getId(a[i]), 0, m-1, T[i], 1);
}
for(int i = 1; i <= n; i++)
{
S[i] = T[0];
}
for(int i = 0; i < q; i++)
{
if(Q[i].kind == 0)
{
printf("%d\n", num[query(Q[i].l, Q[i].r, Q[i].k)]);
}
else
{
update2(Q[i].l, getId(a[Q[i].l]), -1);
update2(Q[i].l, getId(Q[i].r), 1);
a[Q[i].l] = Q[i].r;
}
}
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d %d", &n, &q);
cal();
}
return 0;
}
/*
2
5 3
3 2 1 4 7
Q 1 4 3
Q 2 5 3
*/