Dynamic_Rankings(k番目の最大ダイナミックレンジ)

2112 - ハプニング

\ [\ \]

(この質問は、ツリーのフェンウィックツリーセット会長を言う人は、会長の木を誤解している必要がありますです!)

ここでは、書き込みに解決するために、フェンウィックツリーカバーツリーラインを使用します

まず第一に、私たちが持っている必要がn個の木のツリーライン(ない\(N ^ 2 \)スペース、慌てる必要はありません)

当社は、これらのメモリ・セグメントツリーの範囲$ [L、R] $いくつかの番号を使用します

当社のセグメントツリーが減算されるという考えに基づいて、ツリーの会長、レコード接頭辞

プレフィックスを更新するため、私たちは迅速に更新しなければならないので、木の配列は、書くこと

実際には、木の本質は、ここでは、ツリーラインの会長ではなく、動的セグメントツリーのオープンポイント

(どちらも有意差あり)

これは、シングルポイント変更会長の数であります

struct Functional_SegmentTree{
    void Add(int p,int pre,int l,int r,int x,int y){
        s[p]=s[pre]+y;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(x<=mid) rs[p]=rs[pre],Add(ls[p]=++cnt,ls[pre],l,mid,x,y);
        else ls[p]=ls[pre],Add(rs[p]=++cnt,rs[pre],mid+1,r,x,y); 
    }
};

パス上のすべての点は、新しいノードをオープンする、実際には固定ポイントは、あなたが息子にアクセスしたいだけの時に、新しいセグメントツリーのポイントを開くことはありませんが、開くのに必要なときにはまだ開いていません

だから、コードは次のようになります。

void Add(int p,int l,int r,int x,int y){
    s[p]+=y;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(x<=mid) Add(ls[p]?ls[p]:(ls[cnt+1]=rs[cnt+1]=s[cnt+1]=0,ls[p]=++cnt),l,mid,x,y);
    else Add(rs[p]?rs[p]:(ls[cnt+1]=rs[cnt+1]=s[cnt+1]=0,rs[p]=++cnt),mid+1,r,x,y); 
}

(わずかな圧力線)

だから、全体のツリーは、固定小数点セグメントツリーの配列を更新する必要があります

しかし、この問題のカードスペースのために (あまりにも悪)

したがって、我々は最初の元の値を保存することができ会長ツリーを開く必要があります

(フェンウィックツリー更新空間的複雑であるため、これは?スペースを節約することができますなぜ\()\)^ 2(N-を記録し、木の会長)は、Aのnログを(更新されます)

社長のためので、このコード

const int N=50100,M=10010,K=1520110;
int n,m;

int ncnt;
int a[N],b[N+M],c[M],d[M],e[M];
int cnt;
int ls[K],rs[K],s[K];
int rt[N];

struct hjt{
    void Add(int p,int pre,int l,int r,int x,int y){
        s[p]=s[pre]+y;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(x<=mid) rs[p]=rs[pre],Add(ls[p]=++cnt,ls[pre],l,mid,x,y);
        else ls[p]=ls[pre],Add(rs[p]=++cnt,rs[pre],mid+1,r,x,y); 
    }
}H;
struct sts{
    void Add(int p,int l,int r,int x,int y){
        s[p]+=y;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(x<=mid) Add(ls[p]?ls[p]:(ls[cnt+1]=rs[cnt+1]=s[cnt+1]=0,ls[p]=++cnt),l,mid,x,y);
        else Add(rs[p]?rs[p]:(ls[cnt+1]=rs[cnt+1]=s[cnt+1]=0,rs[p]=++cnt),mid+1,r,x,y); 
    }
    int T[N];
    vector <int> X,Y;
    int Que(int l,int r,int k){
        if(l==r) return l;
        int mid=(l+r)>>1;
        int t=0;
        rep(i,0,X.size()-1) t+=s[ls[X[i]]];
        rep(i,0,Y.size()-1) t-=s[ls[Y[i]]];
        if(t>=k) {
            rep(i,0,X.size()-1) X[i]=ls[X[i]];
            rep(i,0,Y.size()-1) Y[i]=ls[Y[i]];
            return Que(l,mid,k);
        } else {
            rep(i,0,X.size()-1) X[i]=rs[X[i]];
            rep(i,0,Y.size()-1) Y[i]=rs[Y[i]];
            return Que(mid+1,r,k-t);
        }
    }
    int query(int l,int r,int k){
        int p=r; X.clear();X.push_back(rt[r]);
        while(p) X.push_back(T[p]),p-=p&-p; 
        p=l-1;Y.clear();Y.push_back(rt[l-1]);
        while(p) Y.push_back(T[p]),p-=p&-p; 
        return Que(1,ncnt,k);
    }
    void Upd(int p,int x,int y){
        while(p<=n) Add(T[p]?T[p]:(ls[cnt+1]=rs[cnt+1]=s[cnt+1]=0,T[p]=++cnt),1,ncnt,x,y),p+=p&-p;
    }
}S;

char opt[N][1];

int main(){
    rep(kase,1,rd()){
        n=rd(),m=rd();
        cnt=0; memset(S.T,0,sizeof S.T);
        rep(i,1,n) a[i]=b[i]=rd();
        ncnt=n;
        rep(i,1,m) {
            scanf("%s",opt[i]);
            if(opt[i][0]=='Q'){
                c[i]=rd(),d[i]=rd(),e[i]=rd();
            } else {
                c[i]=rd(),d[i]=rd();
                b[++ncnt]=d[i];
            }
        }
        sort(b+1,b+ncnt+1);ncnt=unique(b+1,b+ncnt+1)-b-1;
        rep(i,1,n) {
            a[i]=lower_bound(b+1,b+ncnt+1,a[i])-b;
            H.Add(rt[i]=++cnt,rt[i-1],1,ncnt,a[i],1);
        }
        rep(i,1,m){
            if(opt[i][0]=='Q'){
                int ans=S.query(c[i],d[i],e[i]);
                printf("%d\n",b[ans]);
            }else {
                d[i]=lower_bound(b+1,b+ncnt+1,d[i])-b;
                S.Upd(c[i],a[c[i]],-1);
                S.Upd(c[i],a[c[i]]=d[i],1);
            }
        }
    }
}

おすすめ

転載: www.cnblogs.com/chasedeath/p/11259367.html