zoukankan      html  css  js  c++  java
  • 【算法#1】分块

    分块我cnm我爱分块!

    今天学了点分块板子,仍然不甚熟练,其中第二题就把我卡了至少一两个小时。

    题外话就不说了,把板子挂在这里,本来也不是我的,但是把码风改掉了。

    const int maxn=x,maxm=y;//maxm 一般为sqrt(maxn) 
    int n,len,num;//len:分块长度,num:分块数量。 
    int a[maxn],bl[maxn],l[maxm],r[maxm]; //bl[i] : i点属于哪一个分块,l,r是分块的左右点。
    void build() {
        cin>>n;
        for(int i=1,i<=n,i++)
            cin>>a[i];
        len=sqrt(n);//分块长度
        num=(n-1)/len+1;//分块数量
        for(int i=1,i<=n,i++)
            bl[i]=(i-1)/len+1;//确定每个点的归属
        for(int i=1,i<=num,i++){
            l[i]=(i-1)*len+1;
            r[i]=i*len;//确定分块边界
        }
        r[num]=n;//最后一个分块端点为n!
    }
    void update(int l,int r,int v) {
        // 修改的左右端点和传入参数。(...)看情况而定
        if(bl[L]==bl[R])//如果共块
            for(int i=l;i<=r;i++)
                Do Something...;//直接暴力
        else {
            for(int i=bl[L]+1;i<=bl[R]-1;i++)
                Do Something...;//这里的i枚举的是分块
            for(int i=L;i<=r[bl[L]];i++)
                Do Something...;// 这里的i枚举的是点
            for(int i=l[bl[R]];i<=r;i++)
                Do Something...;// 同上
        }
    }
    int res(int l,int r,int v) {
        // 所求的左右端点和传入参数。(...)看情况而定,和update很像。
        int ans=0;
        if(bl[l]==bl[r])
            for(int i=L;i<=r;i++)
                Do Something...;//原生态暴力
        else {
            for(int i=bl[l]+1;i<=bl[r]-1;i++)
                Do Something...;//对块进行处理
            for(int i=L;i<=r[bl[l]];i++)
                Do Something...;//对左角块进行处理
            for(int i=l[bl[r]];i<=r;i++)
                Do Something...;//对右角块进行处理
        }
        return ans;
    }
    

    把板子偷来看懂了之后去做了一下LibreOJ上的数列分块模板题。

    LibreOJ

    第一题没什么难度,很快就AC了。

    然而,我被第二题一个不知道说是毒瘤好还是我不熟练好的一个地方卡住了,卡了大概一两个小时。

    具体是这样的,我在处理result的时候,没有对给定区间整块外的那些部分加上他们所属块的标记,居然犯了这么蠢的错误,太菜了。

    代码贴在了剪贴板上:Paste

    明天,或者找些时间把剩下几题写了。//其他一些不是太标准的操作的模板也在代码里了

    Update at 11.6

    又是一如既往地被卡了一两个小时,还是没有给元素加上所在区间标记的问题……不过既然这样我是怎么拿到70分的……

    for(int i=bl[l]+1;i<=bl[r]-1;i++){
                int cur=lower_bound(bc[i].begin(),bc[i].end(),c-dv[i])-bc[i].begin();
                if(cur)
                    res=max(res,bc[i][cur-1]);
            }
    

    for(int i=bl[l]+1;i<=bl[r]-1;i++){
                int cur=lower_bound(bc[i].begin(),bc[i].end(),c-dv[i])-bc[i].begin();
                if(cur)
                    res=max(res,bc[i][cur-1]+dv[i]);
            }
    

    我找你找得好苦啊!下次再犯,我就……我就……什么也不干

    下午切了分块4,还是被卡了一会,不过有了之前的经验这次错误很快就找到了。

    原题要求我们做区间加法和区间求和,我虽然对区间做了标记,也在处理元素的时候加上了标记,但是,在对区间求和的时候加上的值应当是标记乘以这个区间的长度,我却只加了一个导致爆零两次……

  • 相关阅读:
    kafka消费者如何才能从头开始消费某个topic的全量数据
    kafka消费者客户端启动之后消费不到消息的原因分析
    JMeter测试工具中的参数化使用[函数助手]
    在IDEA中使用gradle配置打可执行jar包[可执行jar与其所依赖的jar分离]
    一次tomcat配置参数调优Jmeter压力测试记录前后对比
    IntelliJ IDEA 14.1.4导入项目启动报错:Error during artifact deployment.[组件部署期间出错]
    BZOJ2861 : 双向边定向为单向边
    BZOJ4313 : 三维积木
    BZOJ4714 : 旋转排列
    BZOJ1395 : [Baltic2005]Trip
  • 原文地址:https://www.cnblogs.com/Schwarzkopf-Henkal/p/11809848.html
Copyright © 2011-2022 走看看