标签:play std 题意 name pac 主席树 没有 线段树 col
题意:带修求区间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 (动态开点权值线段树 + 树状数组)
标签:play std 题意 name pac 主席树 没有 线段树 col
原文地址:https://www.cnblogs.com/lwqq3/p/11315693.html