• 分块入门(学习笔记)


    分块就是通过比较暴力的方式去处理一些数据结构问题

    分块的复杂度分析

    分块核心思想就是快速处理整块,暴力处理零散部分

    每次处理零散部分之前,要先将零散块的标记清空

    练习:

    hzwer数列入门九题

    bzoj 蒲公英:

    询问区间最小众数

    预处理区间 l,r 内的最小众数,询问时整块和零散块分别询问,比较一下

    注意!! 写代码的时候要分清楚块的编号和原始编号啊qaq

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<stack>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int maxn = 50010;
    int n,m,q,blo;
    int a[maxn],b[maxn],c[maxn],bl[maxn],f[1000][1000],g[1000][1000],sum[1000][maxn];
    int v[1000][maxn];
    
    void calc(){ int l=1,r=n; while(l<=r) {int mid=(l+r)/2; if(mid*mid*mid<=n) blo=mid,l=mid+1; else r=mid-1; } }
    
    int query(int l,int r){
        int res=0; int mx=0,z=0;
        memset(c,0,sizeof(c));
        for(int i=l;i<=min(r,bl[l]*blo);++i) c[a[i]]++;
        if(bl[l]!=bl[r])
            for(int i=(bl[r]-1)*blo+1;i<=r;++i)
                c[a[i]]++;
        if(bl[r]-1>bl[l])
            for(int j=1;j<=q;++j)
                c[j]+=sum[bl[r]-1][j]-sum[bl[l]][j];
        for(int i=1;i<=q;++i){
            if(c[i]>mx){
                mx=c[i];
                z=i;
            }
        }
        if(mx<g[bl[l]+1][bl[r]-1]){
            z=f[bl[l]+1][bl[r]-1];
        }else if(mx==g[bl[l]+1][bl[r]-1]){
            z=min(z,f[bl[l]+1][bl[r]-1]);
        }
        return z;
    }
    
    ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f;}
    int main(){
        n=read(),m=read(); blo=sqrt(n);
        for(int i=1;i<=n;++i){ a[i]=read(),b[i]=a[i]; bl[i]=(i-1)/blo+1;  }
        sort(b+1,b+1+n);
        
        q=unique(b+1,b+1+n)-b-1;
        for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+1+q,a[i])-b;
        
        for(int i=1;i<=bl[n];++i){
            for(int j=1;j<=q;++j){
                sum[i][j]+=sum[i-1][j];
            } 
            for(int k=(i-1)*blo+1;k<=min(i*blo,n);k++){
                ++sum[i][a[k]];
            }
        }
        for(int i=1;i<=bl[n];++i){
            int res,mx;
            memset(c,0,sizeof(c));
            for(int j=i;j<=bl[n];++j){
                res=0,mx=0;
                for(int k=(j-1)*blo+1;k<=min(j*blo,n);++k){
                    ++c[a[k]];
                }
                for(int k=1;k<=q;++k)
                    if(c[k]>mx){
                        mx=c[k];
                        res=k;
                    }
                g[i][j]=mx;
                f[i][j]=res;
            }
        }
        int ans=0;
        int l,r;
        for(int i=1;i<=m;++i){
            l=read(),r=read();
            l=(l+b[ans]-1)%n+1; r=(r+b[ans]-1)%n+1;
            if(l>r) swap(l,r);
            ans=query(l,r);
            printf("%d\n",b[ans]);
        }
        return 0;
    }
  • 相关阅读:
    Substrings(hdu 4455)
    打砖块(codevs 1257)
    AFO
    愿 你 出 走 半 生 , 归 来 仍 是 少 年
    洛谷 2691逃离
    51Nod 1021 石子归并
    洛谷 P3047 [USACO12FEB]附近的牛Nearby Cows
    codevs 2072 分配房间
    codevs 1388 砍树
    codevs 1288 埃及分数
  • 原文地址:https://www.cnblogs.com/tuchen/p/10534798.html
Copyright © 2020-2023  润新知