zoukankan      html  css  js  c++  java
  • 动态求区间K大值(权值线段树)

    我们知道我们可以通过主席树来维护静态区间第K大值。我们又知道主席树满足可加性,所以我们可以用树状数组来维护主席树,树状数组的每一个节点都可以开一颗主席树,然后一起做。

    我们注意到树状数组的每一棵树都和前一颗树没有关系,so,并不需要可持久化,一个朴素的权值线段树就可以啦。

    我们知道普通的线段树是刚开始就把所有的节点都开了,但我们发现并不需要,因为每个点里的操作并不是很多,很大一部分的节点是用不到的,那么我们就可以不开。用Ls 和 Rs 来记左右儿子的地址,随用随开即可。

    #include<bits/stdc++.h>
    #define N 100005
    #define mid ((l+r)>>1)
    using namespace std;
    inline int lowbit(int x){return x&-x;}
    int n,m,sz,totn,totx,toty,a[N],b[N<<1],ca[N],cb[N],cc[N];
    int xx[N],yy[N],rt[N],size[100*N],ls[100*N],rs[100*N];
    void ins(int l,int r,int x,int q,int v){
        size[x]+=v;
        if (l==r) return;
        if (q<=mid) { if (!ls[x]) ls[x]=++sz; ins(l,mid,ls[x],q,v);
        } else { if (!rs[x]) rs[x]=++sz; ins(mid+1,r,rs[x],q,v);    
        }
    }
    int query(int l,int r,int q){
        if(l==r)return l; int sum=0;
        for(int i=1;i<=totx;i++)sum-=size[ls[xx[i]]];
        for(int i=1;i<=toty;i++)sum+=size[ls[yy[i]]];
        if(q<=sum){
            for(int i=1;i<=totx;i++)xx[i]=ls[xx[i]];
            for(int i=1;i<=toty;i++)yy[i]=ls[yy[i]];
            return query(l,mid,q);
        }
        else{
            for(int i=1;i<=totx;i++)xx[i]=rs[xx[i]];
            for(int i=1;i<=toty;i++)yy[i]=rs[yy[i]];
            return query(mid+1,r,q-sum);
        }
    }
    void add(int x,int v){
        int k=lower_bound(b+1,b+totn+1,a[x])-b;
        for(int i=x;i<=n;i+=lowbit(i))ins(1,totn,rt[i],k,v);
    }
    inline int read(){
        int f=1,x=0;char ch;
        do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
        do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
        return f*x;
    }
    int main(){char s[20];
        n=read();m=read();
        for(int i=1;i<=n;i++)a[i]=read(),b[++totn]=a[i];
        for(int i=1;i<=m;i++){
            scanf("%s",s);ca[i]=read();cb[i]=read();
            if(s[0]=='1')cc[i]=read();else b[++totn]=cb[i];
        }
        sort(b+1,b+totn+1);
        totn=unique(b+1,b+totn+1)-b-1;
        for (int i=1;i<=n;i++) rt[i]=i; sz=n;
        for(int i=1;i<=n;i++)add(i,1);
        for(int i=1;i<=m;i++){
            if(cc[i]){
                totx=toty=0;
                for(int j=ca[i]-1;j;j-=lowbit(j))xx[++totx]=rt[j];
                for(int j=cb[i];j;j-=lowbit(j))yy[++toty]=rt[j];
                printf("%d
    ",b[query(1,totn,cc[i])]);
            }
            else{add(ca[i],-1);a[ca[i]]=cb[i];add(ca[i],1);}
        }
    }

    就酱紫。

  • 相关阅读:
    getSupportFragmentManager要用在FragmentActivity及其子类中
    nginx 配置php
    openwrt 安装 ser2net 配置
    stm32 hid 键盘描述
    外部中断实验
    stm32 UART串口
    stm32 按键
    小结-stm32 驱动LED灯
    ASCII 计算机码
    debian/ubuntu安装桌面环境
  • 原文地址:https://www.cnblogs.com/rrsb/p/7955717.html
Copyright © 2011-2022 走看看