zoukankan      html  css  js  c++  java
  • [BZOJ 3196] 二逼平衡树

    Link:

    BZOJ 3196 传送门

    Solution:

    最直观的的思路是用线段树套平衡树

    不过一看到区间第$k$大就又忍不住去写最近刚练的带修改主席树了

    感觉自己数据结构题灵活变通的能力还不够强啊,一开始$naive$得觉得不好算排名……

    区间第$k$大和修改的操作和$Dynamic Rankings$那道经典题完全相同

    对于排名只要利用每个节点的$cnt$计算小于等于$k-1$的个数就能算出$k$的排名了

    而后面两个询问完全可以用前两个操作求出:

    先算出前驱/后继的排名$t$,再求第$t$大的值就行了

    Tip:注意离散化时要包含所有询问中出现的值,否则$lower\_ bound$时会出锅……

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXN=5e4+10;
    struct Query{int l,r,k,op;}qry[MAXN];
    struct PrTree{int ls,rs,cnt;}seg[MAXN*100];
    int n,m,dat[MAXN],dsp[MAXN*6],rt[MAXN],L[MAXN],R[MAXN],cntl,cntr,tot,cnt;
    
    int lowbit(int x){return x&(-x);}
    int idx(int x)
    {return lower_bound(dsp+1,dsp+tot+1,x)-dsp;}
    void Update(int &cur,int pos,int val,int l,int r)
    {
        if(!cur) cur=++cnt;
        seg[cur].cnt+=val;
        if(l==r) return;int mid=(l+r)>>1;
        if(pos<=mid) Update(seg[cur].ls,pos,val,l,mid);
        else Update(seg[cur].rs,pos,val,mid+1,r);
    }
    int Query(int cur,int pos,int l,int r)
    {
        if(l==r) return seg[cur].cnt;
        int mid=(l+r)>>1;
        if(pos<=mid) return Query(seg[cur].ls,pos,l,mid);
        else return Query(seg[cur].rs,pos,mid+1,r)+seg[seg[cur].ls].cnt;
    }
    int Kth(int k,int l,int r)
    {
        if(l==r) return l;
        int mid=(l+r)>>1,sum=0;
        for(int i=1;i<=cntl;i++) sum-=seg[seg[L[i]].ls].cnt;
        for(int i=1;i<=cntr;i++) sum+=seg[seg[R[i]].ls].cnt;
        
        if(k<=sum)
        {
            for(int i=1;i<=cntl;i++) L[i]=seg[L[i]].ls;
            for(int i=1;i<=cntr;i++) R[i]=seg[R[i]].ls;
            return Kth(k,l,mid);
        }
        else
        {
            for(int i=1;i<=cntl;i++) L[i]=seg[L[i]].rs;
            for(int i=1;i<=cntr;i++) R[i]=seg[R[i]].rs;
            return Kth(k-sum,mid+1,r);
        }
    }
    
    void upd(int pos,int val)
    {
        for(int i=pos;i<=n;i+=lowbit(i))
            Update(rt[i],dat[pos],val,1,tot);
    }
    int find_rank(int l,int r,int k)
    {
        int sum=0;
        for(int i=l-1;i;i-=lowbit(i))
            sum-=Query(rt[i],k,1,tot);
        for(int i=r;i;i-=lowbit(i))
            sum+=Query(rt[i],k,1,tot);
        return sum;
    }
    int find_kth(int l,int r,int k)
    {
        cntl=cntr=0;
        for(int i=l-1;i;i-=lowbit(i)) L[++cntl]=rt[i];
        for(int i=r;i;i-=lowbit(i)) R[++cntr]=rt[i];
        return dsp[Kth(k,1,tot)];
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&dat[i]),dsp[++tot]=dat[i];
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&qry[i].op,&qry[i].l,&qry[i].r);
            if(qry[i].op==3) dsp[++tot]=qry[i].r;
            else
            {//一定要将全部数据录入离散化数组! 
                scanf("%d",&qry[i].k);
                if(qry[i].op!=2) dsp[++tot]=qry[i].k;
            }
        }
        sort(dsp+1,dsp+tot+1);tot=unique(dsp+1,dsp+tot+1)-dsp-1;
        
        for(int i=1;i<=n;i++)
            dat[i]=idx(dat[i]),upd(i,1);
        
        for(int i=1;i<=m;i++)
        {
            int l=qry[i].l,r=qry[i].r,k=qry[i].k;
            switch(qry[i].op)
            {
                case 1:printf("%d
    ",find_rank(l,r,idx(k)-1)+1);break;
                case 2:printf("%d
    ",find_kth(l,r,k));break;
                case 3:upd(l,-1);dat[l]=idx(r);upd(l,1);break;
                case 4:
                {
                    int t=find_rank(l,r,idx(k)-1);
                    if(!t){puts("-2147483647");break;}
                    printf("%d
    ",find_kth(l,r,t));break;
                }
                case 5:
                {
                    int t=find_rank(l,r,idx(k));
                    if(t==r-l+1){puts("2147483647");break;}
                    printf("%d
    ",find_kth(l,r,t+1));break;
                }
            }
        }
        
        return 0;
    }
  • 相关阅读:
    JS可改变列宽table
    无图片,用css border实现尖三角
    IE6下position:fixed;兼容
    巧用cssText属性批量操作样式
    Java
    Java
    Java
    JRebel
    Spring
    ActiveMQ
  • 原文地址:https://www.cnblogs.com/newera/p/9368766.html
Copyright © 2011-2022 走看看