zoukankan      html  css  js  c++  java
  • About 分块

    分块的的复杂度是带根号的。。。。

    然后,它是一种暴力算法

    简单来说就是优化过的暴力

    分块算法会对一个序列(长度为N)进行划分,每一块最多有K个元素,这样就会分为N/K块;

    一般K取sqrt(N),那么块数也有K+1 or K块

    通常实现时,我们用belong【i】示第i个位置所属的块,对于每个块都进行信息维护。

    单点修改时,我们一般先将对应块的标记下传,再暴力更新被修改块的状态

    如果是区间 l,r 修改的话,对于被整块跨过的块直接打标记,两端剩余的部分暴力重构

    至于询问操作,和区间修改类似,对于中间跨过的整块,直接利用块保存的信息统计答案,两端剩余部分打暴力

    m次询问复杂度o(sqrt(N))

    以上就是思路;

    建块:

    void divide()
    {
         //n 个数
        int s=sqrt(n);//分成块的大小为sqrt(n);
        for(int i=1;i<=n;i++)
            belong[i]=(i-1)/s+1;//belong[i]数组表示第i个数所在的块
        int cnt=belong[n];//一共有几块
    
        for(int i=1;i<=cnt;i++) 
        { //设置每一块长度
            sum[i]=add[i]=0;//sum表示此时第i块的总值为几,add表示第i块添加的数的总和
            if(i==cnt) 
            {
                //防止最后一块不足s,size表示每一块的长度
                if (n%s==0) size[i]=s;
                else size[i]=n%s;
            } 
            else size[i]=s;
        }
        for(int i=1;i<=n;i++)
            sum[belong[i]]+=a[i];//i所属的那一块的sum加上ai
    
    }

    修改:

    void modify(int l,int r,int v) 
    {
        //修改
        if (belong[l]==belong[r]) 
        {
            //属于同一分块
            for (int i=l; i<=r; i++)so easy
                a[i]+=v;
            return;
        }
        while (belong[l]==belong[l-1]) 
        {
            //自此往下同上访问
            a[l]+=v;
            l++;
        }
        while (belong[r]==belong[r+1]) 
        {
            a[r]+=v;
            r--;
        }
        for (int i=belong[l]; i<=belong[r]; i++) {
            add[i]+=v;
            sum[i]+=size[i]*v;
        }
    }

    查询:

    int query(int l,int r) 
    {
        //访问
        int ans=0;
        if(belong[l]==belong[r]) ans-=sum[belong[l]];//此处为避免l与r属于同一块画图很好理解,此处不再解释
        while (belong[l]==belong[l-1]) 
        {
            ans+=a[l]+add[belong[l]];//因为l要++,所以l会遍历在从l到r的不整区间中所有的数,so要加a数组
            //**从左到第一个整区间
            l++;
        }
        while(belong[r]==belong[r+1]) 
        {
            //**从最后一个整区间到最后
            ans+=a[r]+add[belong[r]];
            r--;
        }
        for (int i=belong[l]; i<=belong[r]; i++) //加入所有整区间的数
            ans+=sum[i];
        return ans;
    }
  • 相关阅读:
    css样式2 布局 定位 层级 显示
    css与样式
    表单属性、键值对
    表单
    列表、表格
    实体、颜色、路径、标签、超链接、图片
    2018/07/05 html基础
    TP 链接数据库与Model模型的创建
    ThinkPHP 模板循环语法
    tp 单字母函数详解(摘自网络)
  • 原文地址:https://www.cnblogs.com/sssy/p/6878778.html
Copyright © 2011-2022 走看看