「Ynoi2018」未来日记

「Ynoi2018」未来日记

区间x->y,kth值...

不管了,先序列分块...

查询

第k值,假定知道每个数的权值,对值域分块。

对于整块,维护前\(i\)个块当中,值域在\(j\)块里以及值为\(j\)的数的个数,可以方便的询问。

对于边角,直接记值域在\(j\)块里以及值为\(j\)的数的个数,显然\(o(\sqrt n)\)

那么接下来只要先按值域块扫,确定第k值在哪个值域块内,然后块内扫一遍,复杂度\(o(\sqrt n)\)

修改

对于边角,大力重构,暴力修改 前\(i\)个块当中,值域在\(j\)块里以及值为\(j\)的数的个数。

对于整块,可以维护一个并查集,每个点指向相同权值的位置,用top数组记录每种权值的并查集顶端位置。然后x->y就很轻松了对吧...从左到右逐块累加,修改 前\(i\)块 值域在\(j\)块里以及值为\(j\)的数的个数。

总体复杂度\(o((n+m) \sqrt n)\)

#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
#define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
using namespace std;
bool cur1;
char buf[10000000],*p1=buf,*p2=buf;
#define Getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,10000000,stdin),p1==p2)?EOF:*p1++
void in(int &r) {
    static char c;
    r=0;
    while(c=Getchar(),c<48);
    do r=(r<<1)+(r<<3)+(c^48);
    while(c=Getchar(),c>47);
}
const int mn=100005;
const int BLK1=290;
const int BLK2=320;
int n,K,K1,val[mn],F[BLK2][BLK1],T[mn][BLK1];
//F[i][j] 值域i块,在前j块里的数个数
//T[i][j] 值i,在前j块里的数个数 
int fa[mn];
int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
int last[mn],top[BLK1][mn];
#define get_val(x) val[find(x)]
int rebuild(int id,int l1,int r1,int x,int y){
    int l=K*id,r=min(K*id+K-1,n),ct=0;
    int *tp=top[id];
    rep(q,l,r)val[q]=get_val(q),tp[val[q]]=0;
    rep(q,l,r){
        if(q>=l1&&q<=r1&&val[q]==x)val[q]=y,++ct;
        fa[q]=(!last[val[q]]?(tp[val[q]]=q+1,last[val[q]]=q+1):last[val[q]])-1;
    }
    rep(q,l,r)last[val[q]]=0;
    return ct;
}
void cg(int id,int v,int v1,int num){
    int *F1=F[v/K1],*F2=F[v1/K1],*T1=T[v],*T2=T[v1];
    rep(q,id,n/K){
        F1[q]-=num,F2[q]+=num,T1[q]-=num,T2[q]+=num;
    }
}
void change(int l,int r,int fr,int to){
    if(fr==to)return;
    int l_id=l/K,r_id=r/K;
    if(l_id==r_id){
        int ct=rebuild(l_id,l,r,fr,to);
        cg(l_id,fr,to,ct);
    }else{
        int *td,*F1=F[fr/K1],*F2=F[to/K1],*T1=T[fr],*T2=T[to],num=0;
        int ct=rebuild(l_id,l,l_id*K+K-1,fr,to);

        rep(q,l_id,r_id-1){
            F1[q]-=ct,F2[q]+=ct,T1[q]-=ct,T2[q]+=ct;
        }
        
        ct+=rebuild(r_id,r_id*K,r,fr,to);
        
        int ld=T1[l_id+1]-T1[l_id];
        rep(q,l_id+1,r_id-1){
            num+=ld;
            ld=T1[q+1]-T1[q];
            F1[q]-=num,F2[q]+=num,T1[q]-=num,T2[q]+=num;
            
            td=top[q];
            if(td[fr]){
                if(td[to])fa[td[fr]-1]=td[to]-1;
                else val[td[fr]-1]=to,td[to]=td[fr];
                td[fr]=0;
            }
        }
        num+=ct;
        rep(q,r_id,n/K){
            F1[q]-=num,F2[q]+=num,T1[q]-=num,T2[q]+=num;
        }
    }
}
int X[BLK2],Y[mn];
int ask(int l,int r,int k){
    int l_id=l/K,r_id=r/K;
    int ans=0;
    if(l_id==r_id){
        
        rep(q,l,r){
            int v=get_val(q);
            ++X[v/K1],++Y[v];
        }
        
        for(int q=0;;++q){
            if(X[q]>=k){
                rep(w,q*K1,q*K1+K1-1){
                    if(Y[w]>=k){
                        ans=w;
                        break;
                    }
                    k-=Y[w];
                }
                break;
            }
            k-=X[q];
        }
        
        rep(q,l,r){
            int v=get_val(q);
            --X[v/K1],--Y[v];
        }
    }else{
        rep(q,l,l_id*K+K-1){
            int v=get_val(q);
            ++X[v/K1],++Y[v];
        }
        rep(q,r_id*K,r){
            int v=get_val(q);
            ++X[v/K1],++Y[v];
        }
        
        
        for(int q=0;;++q){
            int v=F[q][r_id-1]-F[q][l_id]+X[q];
            if(v>=k){
                rep(w,q*K1,q*K1+K1-1){
                    if(T[w][r_id-1]-T[w][l_id]+Y[w]>=k){
                        ans=w;
                        break;
                    }
                    k-=T[w][r_id-1]-T[w][l_id]+Y[w];
                }
                break;
            }
            k-=v;
        }
        
        rep(q,l,l_id*K+K-1){
            int v=get_val(q);
            --X[v/K1],--Y[v];
        }
        rep(q,r_id*K,r){
            int v=get_val(q);
            --X[v/K1],--Y[v];
        }
    }
    return ans;
}
void init(){
    rep(q,0,n)fa[q]=q;
    rep(q,0,n/K){
        int *tp=top[q];
        rep(w,q*K,min(n,q*K+K-1)){
            fa[w]=(!last[val[w]]?(tp[val[w]]=w+1,last[val[w]]=w+1):last[val[w]])-1;
        }
        rep(w,q*K,min(n,q*K+K-1))last[val[w]]=0,++F[val[w]/K1][q],++T[val[w]][q];
        if(q){
            rep(w,0,100000/K1)F[w][q]+=F[w][q-1];
            rep(w,0,100000)T[w][q]+=T[w][q-1];
        }
    }
}
bool cur2;
int main(){
//  cerr<<(&cur2-&cur1)/1024.0/1024<<endl;
    in(n);
    K=sqrt(n)*1.1+1,K1=320;
    --n;
    int m,ty,a,b,x,y;
    in(m);
    rep(q,0,n)in(val[q]);
    init();
    while(m--){
        in(ty),in(a),in(b),in(x);
        if(ty==1)in(y),change(a-1,b-1,x,y);
        else printf("%d\n",ask(a-1,b-1,x));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/klauralee/p/10925775.html