P2617 Dynamic Rankings (动态开点权值线段树 + 树状数组)
Posted lwqq3
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2617 Dynamic Rankings (动态开点权值线段树 + 树状数组)相关的知识,希望对你有一定的参考价值。
题意:带修求区间k小
题解:回忆在使用主席树求区间k小时 利用前缀和的思想 既然是前缀和 那么我们可以使用更擅长维护前缀和的树状数组
但是这里每一颗权值线段树就不是带版本的 而是维护数组里i号点的权值信息 所以实际上并不是主席树 每一棵和前面一棵并没有共用结点
对于一次修改操作 我们先删去这个点的原信息 再更新进去 树状数组上的点一起跳 可能看代码比较好理解一点
这个方法限制性也很强 必须离线
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 2; int n, m, len, cnt; int a[100005]; int b[200005]; int sum[MAXN * 400]; int ls[MAXN * 400]; int rs[MAXN * 400]; int t[MAXN]; int temp[2][50]; int tot1, tot0; struct node char opt; int u, v, w; E[100005]; void add(int &o, int l, int r, int k, int v) if(!o) o = ++cnt; sum[o] += v; int mid = l + r >> 1; if(l == r) return; if(k <= mid) add(ls[o], l, mid, k, v); else add(rs[o], mid + 1, r, k, v); void update(int x, int pos, int v) for(int i = x; i <= n; i += (i & -i)) add(t[i], 1, len, pos, v); void prepare_query(int l, int r) tot1 = tot0 = 0; for(int i = r; i >= 1; i -= (i & -i)) temp[1][++tot1] = t[i]; for(int i = l; i >= 1; i -= (i & -i)) temp[0][++tot0] = t[i]; int query(int l, int r, int k) if(l == r) return l; int mid = l + r >> 1; int res = 0; for(int i = 1; i <= tot1; i++) res += sum[ls[temp[1][i]]]; for(int i = 1; i <= tot0; i++) res -= sum[ls[temp[0][i]]]; if(res >= k) for(int i = 1; i <= tot1; i++) temp[1][i] = ls[temp[1][i]]; for(int i = 1; i <= tot0; i++) temp[0][i] = ls[temp[0][i]]; return query(l, mid, k); else for(int i = 1; i <= tot1; i++) temp[1][i] = rs[temp[1][i]]; for(int i = 1; i <= tot0; i++) temp[0][i] = rs[temp[0][i]]; return query(mid + 1, r, k - res); char s[5]; int main() cnt = 0; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i]; len = n; for(int i = 1; i <= m; i++) scanf("%s", s); E[i].opt = s[0]; if(E[i].opt == ‘Q‘) scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].w); else scanf("%d%d", &E[i].u, &E[i].v); b[++len] = E[i].v; sort(b + 1, b + 1 + len); len = unique(b + 1, b + 1 + len) - b - 1; for(int i = 1; i <= n; i++) int tt = lower_bound(b + 1, b + 1 + len, a[i]) - b; update(i, tt, 1); for(int i = 1; i <= m; i++) if(E[i].opt == ‘Q‘) prepare_query(E[i].u - 1, E[i].v); printf("%d\n", b[query(1, len, E[i].w)]); else int t1 = lower_bound(b + 1, b + 1 + len, a[E[i].u]) - b; update(E[i].u, t1, -1); a[E[i].u] = E[i].v; int t2 = lower_bound(b + 1, b + 1 + len, a[E[i].u]) - b; update(E[i].u, t2, 1); return 0;
以上是关于P2617 Dynamic Rankings (动态开点权值线段树 + 树状数组)的主要内容,如果未能解决你的问题,请参考以下文章