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; }
#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; }