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
posted @ 2018-08-20 08:25  zzzzx  阅读(...)  评论(...编辑  收藏