bzoj1901: Zju2112 Dynamic Rankings
题目链接
bzoj1901: Zju2112 Dynamic Rankings
题解
带修改主席树
只需要在外面套一层BIT
原先的主席树是一串前缀,现在把这个前缀换成bit就是了
建树复杂度是nlog^2n的
对于这题可以只用bit维护修改的内容,开始只需要建常规主席树就好
这样建树的复杂度是nlogn的
代码
#include<cstdio>
#include<algorithm>
#define ls(x) t[x].lc
#define rs(x) t[x].rc
typedef long long ll;
const int maxn = 20007;
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar();
return x * f;
}
#define lowbit(x) (x & -x)
int n,Q,m,a[maxn],mp[maxn];
char s[20];
struct Que{
int type,i,j,k,x,d;
} q[maxn];
inline int bin(int v) {
int l = 1,r = m ;
while(l <= r) {
int mid = l + r >> 1;
if(mp[mid] == v) return mid;
if(mp[mid] > v) r = mid - 1;
else l = mid + 1;
}
return - 1;
}
struct node {
int lc,rc,w;
}t[maxn * 100];
int sz = 0,root[maxn],rt[maxn];
void insert(int &x,int l,int r,int num,int v) {
t[++sz] = t[x];x = sz;
t[x].w += v;
if(l == r) return;
int mid = (l + r) >> 1;
if(num <= mid) insert(t[x].lc,l,mid,num,v);
else insert(t[x].rc,mid + 1,r,num,v);
}
void add(int p,int v) {
int tmp = bin(a[p]);
for(int i = p;i <= n;i += lowbit(i)) insert(root[i],1,m,tmp,v);
}
int q1[maxn],t1,q2[maxn],t2;
int cal() {
int sum1 = 0,sum2 = 0;
for(int i = 1;i <= t1;i ++) sum1 += t[ls(q1[i])].w;
for(int i = 1;i <= t2;i ++) sum2 += t[ls(q2[i])].w;
return sum2 - sum1;
}
int query(int ql,int qr,int k) {
int l = 1,r = m;t1 = t2 = 0;
for(int i = ql - 1;i;i -= lowbit(i)) q1[++ t1] = root[i];
for(int i = qr;i;i -= lowbit(i)) q2[++ t2] = root[i];
ql --;
ql = rt[ql]; qr = rt[qr];
while(l < r) {
int lsiz = cal() + t[ls(qr)].w - t[ls(ql)].w,mid = (l + r) >> 1;
if(k <= lsiz) {
for(int i = 1;i <= t1;++ i) q1[i] = t[q1[i]].lc;
for(int i = 1;i <= t2;++ i) q2[i] = t[q2[i]].lc;
ql = ls(ql);qr = ls(qr);
r = mid;
}else {
for(int i = 1;i <= t1;++ i) q1[i] = t[q1[i]].rc;
for(int i = 1;i <= t2;++ i) q2[i] = t[q2[i]].rc;
ql = rs(ql);qr = rs(qr);
l = mid + 1;k -= lsiz ;
}
}
return l;
}
int main() {
n = read(), Q = read();
char s[10];
for(int i = 1;i <= n;i ++) a[i] = mp[++ m] = read();
for(int i = 1;i <= Q ;i ++) {
scanf("%s",s + 1);
if(s[1] == 'Q') q[i].type = 0,q[i].i = read(),q[i].j = read(),q[i].k = read();
else q[i].type = 1, q[i].x = read(),q[i].d = mp[++ m] = read();
}
std::sort(mp + 1,mp + m + 1);
int p = 1; for(int i = 2;i <= m;i ++) if(mp[i] != mp[i - 1]) mp[++ p] = mp[i]; m = p;
for(int i = 1;i <= n;i ++) rt[i] = rt[i-1],insert(rt[i],1,m,bin(a[i]),1); //这里直接建主席树就好了
for(int i = 1;i <= Q;i ++) {
if(q[i].type == 0) {
printf("%d\n",mp[query(q[i].i,q[i].j,q[i].k)]);
} else {
add(q[i].x,-1);
a[q[i].x] = q[i].d;
add(q[i].x,1);
}
}
return 0;
} 0