ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[模板]动态区间第k小/大(树状数组套主席树

2019-09-22 22:01:36  阅读:203  来源: 互联网

标签:树状 int fix 修改 模板 数组 主席


写挂了好多次,也不太理解

带修改的情况如果还用(权值线段树)主席树,每个点(root[i])维护前缀的某值出现次数,

每次修改需要对此点后面所有主席树修改,共$nlogn$个

这里用树状数组维护前缀和,平时的树状数组实际上每个点维护的是原序列$[i,i-lowbit(i)+1]$这些值,这里也让每个树状数组维护这样一个区间的信息,而不是前缀的,这样修改一个点的值只会影响$logn$棵主席树,查询也是$logn$棵主席树的信息加起来就是整个区间的信息,每次修改存下所有需要修改/查询的主席树,同步进行加减/向下跳,这样每次修改的复杂度就是$log^2 n$的

主席树真的好慢...跑了12s,动态区间第k大还有整体二分等做法

(我竟然连树状数组都不理解...还看了好久树状数组)

#include<bits/stdc++.h>
#define mid (l+r>>1)
#define lbt(x) (x&-x)
using namespace std;
const int maxn=100009;
inline int read(){
    int ret=0,fix=1;char ch;
    while(!isdigit(ch=getchar()))fix=ch=='-'?-1:fix;
    do ret=(ret<<1)+(ret<<3)+ch-'0';
    while(isdigit(ch=getchar()));
    return fix*ret;
}
struct qqq{
    int tp,l,r,x;
}qu[maxn];
int n,m,tot,cnt;
int hsh[maxn<<1],a[maxn];

struct node{
    int l,r,cnt;
}t[maxn*250];
int root[maxn],q[2][30];
inline void insert(int &x,int l,int r,int pos,int val){
    if(!x)x=++tot;
    t[x].cnt+=val;
    if(l==r)return ;
    if(pos<=mid)insert(t[x].l,l,mid,pos,val);
    else insert(t[x].r,mid+1,r,pos,val);
}

inline void add(int pos,int val,int d){
    while(pos<=n){
        insert(root[pos],1,cnt,val,d);
        pos+=lbt(pos);
    }
}
inline int queryt(int l,int r,int k){
    if(l==r)return l;
    int ans=0;
    for(int i=1;i<=q[0][0];i++)ans-=t[t[q[0][i]].l].cnt;
    for(int i=1;i<=q[1][0];i++)ans+=t[t[q[1][i]].l].cnt;
    if(ans>=k){
        for(int i=1;i<=q[0][0];i++)q[0][i]=t[q[0][i]].l;
        for(int i=1;i<=q[1][0];i++)q[1][i]=t[q[1][i]].l;
        return queryt(l,mid,k);
    }
    else{
        for(int i=1;i<=q[0][0];i++)q[0][i]=t[q[0][i]].r;
        for(int i=1;i<=q[1][0];i++)q[1][i]=t[q[1][i]].r;
        return queryt(mid+1,r,k-ans);
    }
}
inline int query(int l,int r,int k){
    l--;
    q[0][0]=q[1][0]=0;
    while(l){
        q[0][++q[0][0]]=root[l];
        l-=lbt(l);
    }
    while(r){
        q[1][++q[1][0]]=root[r];
        r-=lbt(r);
    }
    return queryt(1,cnt,k);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)a[i]=read(),hsh[++cnt]=a[i];
    char op;
    for(int i=1;i<=m;i++){
        op=getchar();
        while(op!='C' &&op!='Q')op=getchar();
        if(op=='Q'){
            qu[i].l=read(),qu[i].r=read(),qu[i].x=read();
        }
        else if(op=='C'){
            qu[i].tp=1;
            qu[i].l=read(),qu[i].x=read();
            hsh[++cnt]=qu[i].x;
        }
    }
    sort(hsh+1,hsh+1+cnt);
    cnt=unique(hsh+1,hsh+1+cnt)-hsh-1;
    for(int i=1;i<=n;i++)a[i]=lower_bound(hsh+1,hsh+1+cnt,a[i])-hsh;
    for(int i=1;i<=m;i++)
    if(qu[i].tp)qu[i].x=lower_bound(hsh+1,hsh+1+cnt,qu[i].x)-hsh;
    
    for(int i=1;i<=n;i++)add(i,a[i],1);//建树 
    
    for(int i=1;i<=m;i++){
        if(qu[i].tp){
            add(qu[i].l,a[qu[i].l],-1);
            add(qu[i].l,qu[i].x,1);
            a[qu[i].l]=qu[i].x;
        }
        else{
            printf("%d\n",hsh[query(qu[i].l,qu[i].r,qu[i].x)]);
        }
    }
}

 

标签:树状,int,fix,修改,模板,数组,主席
来源: https://www.cnblogs.com/superminivan/p/11569505.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有