• loj #6278. 数列分块入门 2


    题目

    题解

    区间修改,询问区间小于c的个数。分块排序,用vector。至于那个块的大小,好像要用到均值不等式
    我不太会。。。就开始一个个试,发现siz=sqrt(n)/4时最快!!!明天去学一下算分块复杂度的方法。
    

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    
    using namespace std;
    const int MAXN = 50005;
    const int N = 1005;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    vector<int> b[N];
    
    int n,siz;
    int a[MAXN],l[N],r[N];
    int num,bl[MAXN],inc[MAXN];
    
    inline void reset(int id){
        b[id].clear();
        for(register int i=l[id];i<=r[id];i++) b[id].push_back(a[i]);
        sort(b[id].begin(),b[id].end());
    }
    
    inline void build(){
        siz=sqrt(n);
        siz/log2(n);
        num=n/siz;
        if(n%siz) num++;
        for(register int i=1;i<=n;i++)
            bl[i]=(i-1)/siz+1;  
        for(register int i=1;i<=num;i++){
            l[i]=(i-1)*siz+1;
            r[i]=i*siz;
        }
        r[num]=n;
        for(register int i=1;i<=num;i++) reset(i);
    }
    
    inline void update(int ql,int qr,int w){
        if(bl[ql]==bl[qr]){
            for(register int i=ql;i<=qr;i++)
                a[i]+=w;
            reset(bl[ql]);
            return;
        }
        for(register int i=ql;i<=r[bl[ql]];i++)
            a[i]+=w;
        reset(bl[ql]);
        for(register int i=bl[ql]+1;i<bl[qr];i++)   
            inc[i]+=w;
        for(register int i=l[bl[qr]];i<=qr;i++)
            a[i]+=w;
        reset(bl[qr]);
    }
    
    inline int query(int ql,int qr,int c){
        int ret=0;
        if(bl[ql]==bl[qr]){
            for(register int i=ql;i<=qr;i++)
                ret+=(a[i]+inc[bl[i]]<c);
            return ret;
        }
        for(register int i=ql;i<=r[bl[ql]];i++)
            ret+=(a[i]+inc[bl[i]]<c);
        for(register int i=l[bl[qr]];i<=qr;i++)
            ret+=(a[i]+inc[bl[i]]<c);
        for(register int i=bl[ql]+1;i<bl[qr];i++){
            int tar=c-inc[i];
            ret+=lower_bound(b[i].begin(),b[i].end(),tar)-b[i].begin();
        }
        return ret;
    }
    
    int main(){
        n=rd();
        for(register int i=1;i<=n;i++) a[i]=rd();
        build();
        for(register int i=1;i<=n;i++){
            int op,L,R,k;
            op=rd();L=rd();R=rd();k=rd();
            if(op==0)
                update(L,R,k);
            else
                printf("%d
    ",query(L,R,k*k));
        }
        return 0;
    }
  • 相关阅读:
    125. Valid Palindrome java solutions
    350. Intersection of Two Arrays II java solutions
    ex25.py 各种函数
    习题21,几个简单的加减乘除函数,注意return的用法。
    文件的写入,但是出了一个bug。(Unicode解码错误:‘gbk’编解码器无法解码位置0中的字节0xff:非法多字节序列)
    读写文件(open(), write())
    who, w, whoami以及id命令的使用
    终端设备与tty、chvt、startx命令
    设置自动登录CentOS7
    docker常用命令
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9677036.html
Copyright © 2020-2023  润新知