The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They have developed a more powerful system such that for N numbers a[1], a[2], ..., a[N], you can ask it like: what is the k-th smallest number of a[i], a[i+1], ..., a[j]? (For some i<=j, 0<k<=j+1-i that you have given to it). More powerful, you can even change the value of some a[i], and continue to query, all the same.

Your task is to write a program for this computer, which

- Reads N numbers from the input (1 <= N <= 50,000)

- Processes M instructions of the input (1 <= M <= 10,000). These instructions include querying the k-th smallest number of a[i], a[i+1], ..., a[j] and change some a[i] to t.

Input

The first line of the input is a single number X (0 < X <= 4), the number of the test cases of the input. Then X blocks each represent a single test case.

The first line of each block contains two integers N and M, representing N numbers and M instruction. It is followed by N lines. The (i+1)-th line represents the number a[i]. Then M lines that is in the following format

Q i j k or
C i t

It represents to query the k-th number of a[i], a[i+1], ..., a[j] and change some a[i] to t, respectively. It is guaranteed that at any time of the operation. Any number a[i] is a non-negative integer that is less than 1,000,000,000.

There're NO breakline between two continuous test cases.

Output

For each querying operation, output one integer to represent the result. (i.e. the k-th smallest number of a[i], a[i+1],..., a[j])

There're NO breakline between two continuous test cases.

Sample Input

2
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3

Sample Output

3
6
3

6


用静态主席树存初始的数字,然后用树状数组套线段树存之后的修改操作,可以保证不会超内存了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
const int maxn = 60505;
const int Maxn = 1000505;
const int low(int x) { return x&-x; }
int T, n, m, a[maxn], b[maxn], c[maxn], tot;
char s[2];

struct question
{
int f, l, r, k;
}p[maxn];

struct Bit
{
int n, m, t, tt;
int L[Maxn], R[Maxn], sum[Maxn], frist[maxn];
int LL[Maxn], RR[Maxn], Sum[Maxn], Frist[maxn];
void build(int x, int y)
{
tt = t = n = x; m = y;
for (int i = 0; i <= n; i++) L[i] = R[i] = sum[i] = 0, frist[i] = i;
for (int i = 0; i <= n; i++) LL[i] = RR[i] = Sum[i] = 0, Frist[i] = i;
}
void Insert(int x, int y, int z)
{
int bef = Frist[x - 1], now = Frist[x], l, r, mid;
Sum[now] = Sum[bef] + z;
for (l = 1, r = m; l < r;)
{
mid = (l + r) >> 1;
if (y <= mid)
{
r = mid; LL[now] = ++tt;
RR[now] = RR[bef]; Sum[tt] = Sum[LL[bef]] + z;
now = LL[now]; bef = LL[bef];
}
else
{
l = mid + 1; LL[now] = LL[bef];
RR[now] = ++tt; Sum[tt] = Sum[RR[bef]] + z;
now = RR[now]; bef = RR[bef];
}
LL[tt] = RR[tt] = 0;
}
}
void add(int x, int l, int r, int y, int z)
{
sum[x] += z;
if (l == r) return;
else
{
int mid = (l + r) >> 1;
if (y <= mid)
{
if (!L[x]) { L[x] = ++t; L[t] = R[t] = sum[t] = 0; }
add(L[x], l, mid, y, z);
}
else
{
if (!R[x]) { R[x] = ++t; L[t] = R[t] = sum[t] = 0; }
add(R[x], mid + 1, r, y, z);
}
}
}
void insert(int x, int y, int z)
{
for (int i = x; i <= n; i += low(i)) add(frist[i], 1, m, y, z);
}
int query(int x, int y, int k)
{
int A, B, a[50], b[50];
A = B = 0;
for (int i = x - 1; i; i -= low(i)) a[A++] = frist[i];
for (int i = y; i; i -= low(i)) b[B++] = frist[i];
int l, r, result, mid, u = Frist[x - 1], v = Frist[y];
for (l = 1, r = m; l < r;)
{
result = 0; mid = (l + r) >> 1;
for (int i = 0; i < B; i++) result += sum[L[b[i]]];
for (int i = 0; i < A; i++) result -= sum[L[a[i]]];
result += Sum[LL[v]] - Sum[LL[u]];
if (k <= result)
{
for (int i = 0; i < B; i++) b[i] = L[b[i]];
for (int i = 0; i < A; i++) a[i] = L[a[i]];
u = LL[u]; v = LL[v]; r = mid;
}
else
{
for (int i = 0; i < B; i++) b[i] = R[b[i]];
for (int i = 0; i < A; i++) a[i] = R[a[i]];
l = mid + 1; k -= result; u = RR[u]; v = RR[v];
}
}
return l;
}
}bit;

int main()
{
cin >> T;
while (T--)
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
tot = n;
for (int i = 1; i <= m; i++)
{
scanf("%s", s);
if (s[0] == 'Q') p[i].f = 1, scanf("%d%d%d", &p[i].l, &p[i].r, &p[i].k);
else
{
p[i].f = 0; p[i].k = ++tot;
scanf("%d%d", &p[i].l, &p[i].r);
b[tot] = a[tot] = p[i].r;
}
}
sort(a + 1, a + tot + 1);
int u = unique(a + 1, a + tot + 1) - a - 1;
bit.build(n, u);
for (int i = 1; i <= tot; i++) c[i] = lower_bound(a + 1, a + u + 1, b[i]) - a;
for (int i = 1; i <= n; i++) bit.Insert(i, c[i], 1);
for (int i = 1; i <= m; i++)
{
if (p[i].f) printf("%d\n", a[bit.query(p[i].l, p[i].r, p[i].k)]);
else if (c[p[i].l] != c[p[i].k])
{
bit.insert(p[i].l, c[p[i].l], -1);
bit.insert(p[i].l, c[p[i].k], 1);
c[p[i].l] = c[p[i].k];
}
}
}
return 0;
}

写了个线段树套treap的,结果炸内存了,是指针的问题吗。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<functional>
using namespace std;
typedef long long LL;
const int maxn = 5e4 + 10;
const int mod = 1e9 + 7;
int T, n, m, l, r, k, a[maxn];
char ch[5];

struct Node
{
int v, p, cnt, inc;
Node *l, *r;
Node(int v = 0, int p = 0) :v(v), p(p){ l = r = NULL; cnt = inc = 1; }
void clear(){ if (l) l->clear(); if (r) r->clear(); delete[]this; }
};

struct Treap
{
#define node Node*
#define now (*root)
Node *root;
void Count(node root)
{
root->cnt = root->inc;
if (root->l) root->cnt += root->l->cnt;
if (root->r) root->cnt += root->r->cnt;
}
void rotate_left(node *root)
{
node right = now->r;
now->r = right->l;
right->l = now;
now = right;
Count(now->l); Count(now);
}
void rotate_right(node *root)
{
node left = now->l;
now->l = left->r;
left->r = now;
now = left;
Count(now->r); Count(now);
}
void Insert(node *root, int v, int p)
{
if (!now) { now = new Node(v, p); return; }
if (now->v == v) now->inc++;
else if (v < now->v)
{
Insert(&(now->l), v, p);
if (now->l->p < now->p) rotate_right(root);
}
else
{
Insert(&(now->r), v, p);
if (now->r->p < now->p) rotate_left(root);
}
Count(now);
}
void add(int x){ Insert(&root, x, rand() % mod); }
void Delete(node *root, int v)
{
if (!now) return;
if (v < now->v) Delete(&(now->l), v);
if (v > now->v) Delete(&(now->r), v);
if (v == now->v)
{
if (now->inc > 1) now->inc--;
else if (!now->l || !now->r)
{
node temp = now;
if (now->l) now = now->l; else now = now->r;
delete[] temp; return;
}
else
{
if (now->l->p < now->r->p)
{
rotate_right(root);
Delete(&(now->r), v);
}
else
{
rotate_left(root);
Delete(&(now->l), v);
}
}
}
Count(now);
}
void dec(int x){ Delete(&root, x); }
int find(int x)
{
int ans = 0;
for (node temp = root; temp;)
{
int left = temp->l ? temp->l->cnt : 0;
if (x < temp->v) temp = temp->l;
else
{
if (x == temp->v) return ans + left;
ans += left + temp->inc;
temp = temp->r;
}
}
return ans;
}
void clear(){ if (root) root->clear(); root=NULL; }
};

struct Tree
{
Treap f[maxn * 4];
void insert(int x, int l, int r)
{
f[x].clear();
if (l == r) { scanf("%d", &a[l]); f[x].add(a[l]); return; }
int mid = l + r >> 1;
insert(x << 1, l, mid);
insert(x << 1 | 1, mid + 1, r);
for (int i = l; i <= r; i++) f[x].add(a[i]);
}
int find(int x, int l, int r, int ll, int rr, int v)
{
if (ll <= l&&r <= rr) return f[x].find(v);
int mid = l + r >> 1, ans = 0;
if (ll <= mid) ans += find(x << 1, l, mid, ll, rr, v);
if (rr > mid) ans += find(x << 1 | 1, mid + 1, r, ll, rr, v);
return ans;
}
void change(int x, int l, int r, int w, int u, int v)
{
f[x].dec(u); f[x].add(v);
if (l == r) return;
int mid = l + r >> 1;
if (w <= mid) change(x << 1, l, mid, w, u, v);
else change(x << 1 | 1, mid + 1, r, w, u, v);
}
void revese(int x, int l, int r)
{
f[x].clear();
if (l == r) return;
int mid = l + r >> 1;
revese(x << 1, l, mid);
revese(x << 1 | 1, mid + 1, r);
}
}st;

int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
st.insert(1, 1, n);
while (m--)
{
scanf("%s", &ch);
if (ch[0] == 'Q')
{
scanf("%d%d%d", &l, &r, &k);
int q = 0, h = 1e9;
while (q < h)
{
int mid = q + h >> 1;
int u = st.find(1, 1, n, l, r, mid);
if (u > k - 1) h = mid - 1;
if (u == k - 1) q = mid;
if (u < k - 1) q = mid + 1;
if (st.find(1, 1, n, l, r, h) == k - 1) q = h; else h--;
}
printf("%d\n", q);
}
else
{
scanf("%d%d", &l, &r);
st.change(1, 1, n, l, a[l], r);a[l]=r;
}
}
st.revese(1, 1, n);
}
return 0;
}


换了数组来写就好啦,线段树套treap


#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
typedef long long LL;
int T, n, m, l, r, k;
char s[5];

struct Treaps
{
const static int maxn = 1e6 + 3e5;
int L[maxn], R[maxn], v[maxn], p[maxn], A[maxn], C[maxn], tot;
void clear(){ A[0] = L[0] = R[0] = C[0] = 0; tot = 1; }
int Node(int V, int P){ L[tot] = R[tot] = 0; v[tot] = V; p[tot] = P; A[tot] = C[tot] = 1; return tot++; }
void Count(int x){ C[x] = A[x] + C[L[x]] + C[R[x]]; }
void rotate_right(int &x)
{
int y = L[x]; L[x] = R[y]; R[y] = x; C[y] = C[x]; Count(x); x = y;
}
void rotate_left(int &x)
{
int y = R[x]; R[x] = L[y]; L[y] = x; C[y] = C[x]; Count(x); x = y;
}
void Insert(int& x, int V, int P)
{
if (!x) { x = Node(V, P); return; }
if (v[x] == V) ++A[x];
else if (V < v[x])
{
Insert(L[x], V, P);
if (p[x]>p[L[x]]) rotate_right(x);
}
else
{
Insert(R[x], V, P);
if (p[x] > p[R[x]]) rotate_left(x);
}
Count(x);
}
void add(int &x, int V){ Insert(x, V, rand()); }
void Delete(int &x, int V)
{
if (!x) return;
if (V < v[x]) Delete(L[x], V);
else if (V > v[x]) Delete(R[x], V);
else if (A[x] > 1) --A[x];
else if (!L[x] || !R[x]) x = L[x] + R[x];
else if (p[L[x]] < p[R[x]]){ rotate_right(x); Delete(R[x], V); }
else { rotate_left(x); Delete(L[x], V); }
Count(x);
}
void dec(int &x, int V) { Delete(x, V); }
int find(int x, int V)
{
int ans = 0;
for (int i = x; i; i = V < v[i] ? L[i] : R[i])
{
if (v[i] <= V) ans += C[L[i]] + A[i];
}
return ans;
}
};

struct Tree
{
const static int maxn = 2e5 + 10;
Treaps t;
int f[maxn], y[maxn];
void clear(){ t.clear(); memset(f, 0, sizeof(f)); }
void insert(int x, int l, int r)
{
if (l == r) { scanf("%d", &y[l]); t.add(f[x], y[l]); return; }
int mid = l + r >> 1;
insert(x << 1, l, mid);
insert(x << 1 | 1, mid + 1, r);
for (int i = l; i <= r; i++) t.add(f[x], y[i]);
}
int find(int x, int l, int r, int ll, int rr, int u)
{
if (ll <= l&&r <= rr) return t.find(f[x], u);
int mid = l + r >> 1, ans = 0;
if (ll <= mid) ans += find(x << 1, l, mid, ll, rr, u);
if (rr > mid) ans += find(x << 1 | 1, mid + 1, r, ll, rr, u);
return ans;
}
void change(int x, int l, int r, int u, int v)
{
t.dec(f[x], y[u]); t.add(f[x], v);
if (l == r) return;
int mid = l + r >> 1;
if (u <= mid) change(x << 1, l, mid, u, v);
else change(x << 1 | 1, mid + 1, r, u, v);
}
}solve;

int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
solve.clear();
solve.insert(1, 1, n);
while (m--)
{
scanf("%s", s);
if (s[0] == 'Q')
{
scanf("%d%d%d", &l, &r, &k);
int q = 0, h = 1e9;
while (q <= h)
{
int mid = q + h >> 1;
int ans = solve.find(1, 1, n, l, r, mid);
if (ans >= k) h = mid - 1; else q = mid + 1;
}
printf("%d\n", q);
}
else
{
scanf("%d%d", &l, &r);
solve.change(1, 1, n, l, r);
solve.y[l] = r;
}
}
}
return 0;
}