ZOJ2112-Dynamic Rankings (树状数组+主席树)

xiaoxiao2021-02-27  152

题意:给你n个数,m次操作:

Q x y z表示查询区间[x,y]中第z小的数是多少;

C x y  表示将第x个位置上的数替换成y;

题解:和http://blog.csdn.net/haut_ykc/article/details/77678882 一样,只是多了修改操作;

要知道每次修改某一个位置上的数都会影响后边的所有线段树,假如暴力更新的话必然会超时。

我们可以考虑用树状数组,因此可以考虑把主席树分成两部分,一部分表示原序列、另一部分表示修改过的即可。

#include<set> #include<map> #include<stack> #include<queue> #include<vector> #include<string> #include<math.h> #include<stdio.h> #include<iostream> #include<string.h> #include<stdlib.h> #include<algorithm> #include<functional> using namespace std; typedef long long ll; #define inf 1000000000 #define mod 1000000007 #define maxn 2600005 #define PI 3.1415926 #define lowbit(x) (x&-x) #define eps 1e-9 int a[60005], b[60005], rt[60005], num, f[60005], used[60005]; int cnt, sum[maxn], ls[maxn], rs[maxn], n, q[10005][4]; void build(int &id, int l, int r) { id = ++cnt; sum[id]=0; if (l == r) return; int mid = (l + r) / 2; build(ls[id], l, mid); build(rs[id], mid + 1, r); } void update(int &id, int l, int r, int last, int val, int k) { id = ++cnt; ls[id] = ls[last]; rs[id] = rs[last]; sum[id] = sum[last] + k; if (l == r) return; int mid = (l + r) / 2; if (val <= mid) update(ls[id], l, mid, ls[last], val, k); else update(rs[id], mid + 1, r, rs[last], val, k); } int sm(int x) { int ans = 0; while (x) { ans += sum[ls[used[x]]]; x -= lowbit(x); } return ans; } int query(int st, int ed, int val) { int i, les, res; int l = 1, r = num; les = rt[st];res = rt[ed]; for (i = st;i > 0;i -= lowbit(i)) used[i] = f[i]; for (i = ed;i > 0;i -= lowbit(i)) used[i] = f[i]; while (l < r) { int mid = (l + r) / 2; int tmp = sm(ed) - sm(st) + sum[ls[res]] - sum[ls[les]]; if (val <= tmp) { r = mid; for (i = st;i > 0;i -= lowbit(i)) used[i] = ls[used[i]]; for (i = ed;i > 0;i -= lowbit(i)) used[i] = ls[used[i]]; les = ls[les];res = ls[res]; } else { l = mid + 1;val -= tmp; for (i = st;i > 0;i -= lowbit(i)) used[i] = rs[used[i]]; for (i = ed;i > 0;i -= lowbit(i)) used[i] = rs[used[i]]; les = rs[les];res = rs[res]; } } return l; } void add(int x, int v, int k) { while (x <= n) { int tmp = f[x]; update(f[x], 1, num, tmp, v, k); x += lowbit(x); } } int main(void) { char c; int T, m, i, j; scanf("%d", &T); while (T--) { cnt = 0; memset(sum, 0, sizeof(sum)); scanf("%d%d", &n, &m); for (i = 1;i <= n;i++) scanf("%d", &a[i]), b[i] = a[i]; num = n; for (i = 1;i <= m;i++) { scanf(" %c", &c); if (c == 'Q') { scanf("%d%d%d", &q[i][1], &q[i][2], &q[i][3]); q[i][0] = 1; } else { scanf("%d%d", &q[i][1], &q[i][2]); b[++num] = q[i][2];q[i][0] = 0; } } sort(b + 1, b + num + 1); num = unique(b + 1, b + num + 1) - b - 1; for (i = 1;i <= num;i++) a[i] = lower_bound(b + 1, b + num + 1, a[i]) - b; build(rt[0], 1, num); for (i = 1;i <= n;i++) update(rt[i], 1, num, rt[i - 1], a[i], 1); for (i = 1;i <= n;i++) f[i] = rt[0]; for (i = 1;i <= m;i++) { if (q[i][0] == 1) { int ans = query(q[i][1]-1, q[i][2], q[i][3]); printf("%d\n", b[ans]); } else { int tmp; add(q[i][1], a[q[i][1]], -1); tmp = lower_bound(b + 1, b + num + 1, q[i][2]) - b; add(q[i][1], tmp, 1); a[q[i][1]] = tmp; } } } return 0; } /* 1000 5 5 1 2 3 4 5 Q 2 3 1 Q 1 5 5 C 3 1 Q 2 3 1 Q 2 3 2 5 4 -1 -2 -3 -4 -5 Q 1 3 2 Q 1 3 1 C 2 1 Q 1 5 4 */

转载请注明原文地址: https://www.6miu.com/read-17284.html

最新回复(0)