• [Ynoi2018]未来日记


    "望月悲叹的最初分块" (妈呀这名字好中二啊(谁叫我要用日本轻小说中的东西命名真是作死))

    这里就直接挂csy的题解了,和我的不太一样,但是大概思路还是差不多的,我的做法是和“五彩斑斓的世界”有点类似的维护方法

    先考虑如何求区间第k小值。对序列和权值都进行分块,设bi,j表示前j 块中权值在i 块内的数字个数,ci,j 表示前j 块中数字i 的出现次数。那么对于一个询问[l,r] ,首先将零碎部分的贡献加入到临时数组tb 和tc 中,然后枚举答案位于哪一块,确定位于哪一块之后再暴力枚举答案即可在O(√n) 的时间内求出区间第k小值。

    接着考虑如何实现区间[l,r]x 变成y 的功能。显然对于零碎的两块,可以直接暴力重构整块。对于中间的每个整块,如果某一块不含x ,那么无视这一块;否则如果这一块不含y ,那么只需要将x 映射成y ;否则这一块既有x 又有y ,这意味着x 与y 之间发生了合并,不妨直接暴力重构整块。因为有c 数组,我们可以在O(1) 的时间内知道某一块是否有某个数。

    考虑什么情况下会发生重构,也就是一个块内发生了一次合并的时候。一开始长度为nn 的序列会提供O(n) 次合并的机会,而每次修改会对零碎的两块各提供一次机会,故总合并次数不超过O(n+m) ,因此当发生合并时直接重构并不会影响复杂度。

    那么现在每块中的转换情况只可能是一条条互不相交的链,只需要记录每个初值转换后是什么,以及每个现值对应哪个初值即可。遇到查询的时候,我们需要知道零碎部分每个位置的值,不妨直接重构那两块,然后遍历一遍原数组a即可得到每个位置的值。

    在修改的时候,还需要同步维护b 和c 数组,因为只涉及两个权值,因此暴力修改j 这一维也是可以承受的。

    总时间复杂度O((n+m)√n) ,空间复杂度O(n√n)

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+5,BLO=370;
    int n,m,a[N],p,vec[N],v2[BLO];
    int bl[N],L[BLO],R[BLO];
    int s1[BLO][BLO],s2[BLO][N],id[BLO][N],rid[BLO][BLO],pos[N];
    int sta[20],ttop=0,lp=0;
    char pr[700005];
    template <typename T> inline void read(T &x) {
        x=0;register char flag,c=getchar();while(c<'0'||c>'9')  flag=c,c=getchar();
        while(c>='0'&&c<='9')   x=x*10+(c^48),c=getchar(); if(flag=='-') x=-x;
    }
    template <typename T> inline void print(T x) {
        ttop=0; do { sta[++ttop]=(int)(x%10),x/=10; }while(x);
        while(ttop) pr[lp++]=sta[ttop--]+'0'; pr[lp++]=10;
    }
    inline void reset(int x) { for(register int i=L[x];i<=R[x];++i)    a[i]=rid[x][pos[i]]; }
    inline void change(int bel,int x,int y) {
        int uid=id[bel][x];id[bel][y]=uid,rid[bel][uid]=y,id[bel][x]=0;
    }
    inline void build(int x) {
        for(register int i=1;i<=p;++i)  id[x][rid[x][i]]=0;
        for(register int i=L[x],idx=0;i<=R[x];++i)
            if(!id[x][a[i]])
                id[x][a[i]]=++idx,rid[x][idx]=a[i];
        for(register int i=L[x];i<=R[x];++i)    pos[i]=id[x][a[i]];
    }
    inline void rebuild(int l,int x,int y) {
        for(register int i=bl[l];i<=bl[n];++i) {
            s2[i][x]+=s2[i-1][x],s2[i][y]+=s2[i-1][y];
            s1[i][bl[x]]+=s1[i-1][bl[x]],s1[i][bl[y]]+=s1[i-1][bl[y]];
        }
    }
    inline void modify(int l,int r,int x,int y) {
        if(s2[bl[r]][x]-s2[bl[l]-1][x]==0)  return ;
        for(int i=bl[n];i>=bl[l];--i) {
            s2[i][x]-=s2[i-1][x],s2[i][y]-=s2[i-1][y];
            s1[i][bl[x]]-=s1[i-1][bl[x]],s1[i][bl[y]]-=s1[i-1][bl[y]];
        }
        if(bl[l]==bl[r]) {
            reset(bl[l]);
            for(int i=l;i<=r;++i)
                if(a[i]==x) {
                    a[i]=y;
                    --s2[bl[l]][x],++s2[bl[l]][y];
                    --s1[bl[l]][bl[x]],++s1[bl[l]][bl[y]];
                }
            build(bl[l]),rebuild(l,x,y);return ;
        }
        reset(bl[l]),reset(bl[r]);
        for(int i=l;i<=R[bl[l]];++i)
            if(a[i]==x) {
                a[i]=y;
                --s2[bl[l]][x],++s2[bl[l]][y];
                --s1[bl[l]][bl[x]],++s1[bl[l]][bl[y]];
            }
        for(int i=L[bl[r]];i<=r;++i)
            if(a[i]==x) {
                a[i]=y;
                --s2[bl[r]][x],++s2[bl[r]][y];
                --s1[bl[r]][bl[x]],++s1[bl[r]][bl[y]];
            }
        build(bl[l]),build(bl[r]);
        for(int i=bl[l]+1;i<bl[r];++i) {
            if(!s2[i][x])   continue;
            if(s2[i][y]) {
                reset(i);
                for(int j=L[i];j<=R[i];++j)
                    if(a[j]==x) {
                        a[j]=y;
                        --s2[i][x],++s2[i][y];
                        --s1[i][bl[x]],++s1[i][bl[y]];
                    }
                build(i);
            }
            else {
                s1[i][bl[y]]+=s2[i][x],s1[i][bl[x]]-=s2[i][x];
                s2[i][y]+=s2[i][x],s2[i][x]=0;
                change(i,x,y);
            }
        }
        rebuild(l,x,y);
    }
    inline int ask(int l,int r,int k) {
        int ans=0,sum=0;
        if(bl[l]==bl[r]) {
            reset(bl[l]);for(int i=l;i<=r;++i)  vec[i]=a[i];
            nth_element(vec+l,vec+l+k-1,vec+r+1),ans=vec[l+k-1];
            for(int i=l;i<=r;++i)   vec[i]=0; return ans;
        }
        reset(bl[l]),reset(bl[r]);
        for(int i=l;i<=R[bl[l]];++i)    ++vec[a[i]],++v2[bl[a[i]]];
        for(int i=L[bl[r]];i<=r;++i)    ++vec[a[i]],++v2[bl[a[i]]];
        for(int i=1;i<=bl[N-1];++i) {
            if(sum+v2[i]+s1[bl[r]-1][i]-s1[bl[l]][i]>=k) {
                for(int j=(i-1)*p+1;j<=i*p;j++) {
                    if(vec[j]+s2[bl[r]-1][j]-s2[bl[l]][j]+sum>=k) { ans=j;goto FLAG; }
                    else    sum+=vec[j]+s2[bl[r]-1][j]-s2[bl[l]][j];
                }
            }
            else    sum+=v2[i]+s1[bl[r]-1][i]-s1[bl[l]][i];
        }
        FLAG:
        for(int i=l;i<=R[bl[l]];++i)    --vec[a[i]],--v2[bl[a[i]]];
        for(int i=L[bl[r]];i<=r;++i)    --vec[a[i]],--v2[bl[a[i]]];
        return ans;
    }
    int main() {
        read(n),read(m),p=sqrt(N)+1;
        for(int i=1;i<N;++i) bl[i]=(i-1)/p+1;
        for(int i=1;i<=n;++i) read(a[i]);
        for(int i=1;i<=bl[n];++i)
            L[i]=(i-1)*p+1,R[i]=i*p;R[bl[n]]=n;
        for(int x=1;x<=bl[n];++x)   build(x);
        for(int x=1;x<=bl[n];++x) {
            for(int i=1;i<N;++i)    s2[x][i]=s2[x-1][i];
            for(int i=1;i<=bl[N-1];++i) s1[x][i]=s1[x-1][i];
            for(int i=L[x];i<=R[x];++i) ++s1[x][bl[a[i]]],++s2[x][a[i]];
        }
        for(;m;--m) {
            int opt,x,y;read(opt),read(x),read(y);
            if(opt==1) {int z,w;read(z),read(w),modify(x,y,z,w);}
            else {int k;read(k),print(ask(x,y,k));}
        }
        pr[--lp]=''; puts(pr);
        return 0;
    }
  • 相关阅读:
    Unique Binary Search Trees——LeetCode
    Binary Tree Inorder Traversal ——LeetCode
    Maximum Product Subarray——LeetCode
    Remove Linked List Elements——LeetCode
    Maximum Subarray——LeetCode
    Validate Binary Search Tree——LeetCode
    Swap Nodes in Pairs——LeetCode
    Find Minimum in Rotated Sorted Array——LeetCode
    Linked List Cycle——LeetCode
    VR AR MR
  • 原文地址:https://www.cnblogs.com/zzrblogs/p/10632566.html
Copyright © 2020-2023  润新知