• CodeChef Chef and Churu [分块]


    题意:

    单点修改$a$

    询问$a$的区间和$f$的区间和


    原来普通计算机是这道题改编的吧...

    对$f$分块,预处理$c[i][j]$为块i中$a_j$出现几次,$O(NH(N))$,只要每个块差分加上然后扫一遍就行了不用树状数组之类的

    修改,整块直接改,还要单点修改$a$

    查询,整块直接查,两边暴力查询$a$的区间和

    对$a$的操作可以用树状数组,也可以再分块维护前缀和实现$O(N)-O(1)$

    这样不用带一个log总复杂度$O(NH(N))$

    实测快了0.4s

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int N=1e5+5,M=350;
    typedef unsigned long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,Q,op,x,y;
    ll a[N],s[N];
    int pos[N],m,block;
    struct _Block{int l,r;} b[M], f[N];
    inline void iniBlock(){
        block=sqrt(n); m=(n-1)/block+1;
        for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
        for(int i=1;i<=m;i++) b[i].l=(i-1)*block+1,b[i].r=i*block;
        b[m].r=n;
    }
    struct BlockA{
        ll add[M];
        void Add(int x,ll v){
            for(int i=x;i<=b[pos[x]].r;i++) s[i]+=v;
            for(int i=pos[x]+1;i<=m;i++) add[i]+=v;
        }
        ll fun(_Block &x){
            return s[x.r]+add[ pos[x.r] ] - (s[x.l-1]+add[ pos[x.l-1] ]);
        }
    }A;
    struct Block{
        int c[M][N],s[N];
        ll sum[N];
        void ini(){
            for(int i=1;i<=m;i++){
                for(int j=b[i].l ; j<=b[i].r ; j++)
                    s[ f[j].l ]++,s[ f[j].r+1 ]--;
                int *cc=c[i];
                for(int j=1;j<=n;j++) 
                    cc[j]=cc[j-1]+s[j],sum[i]+=cc[j]*a[j],s[j]=0;
            }
        }
        void cha(int x,ll v){
            ll t=v-a[x]; A.Add(x,t);
            for(int i=1;i<=m;i++) sum[i]+=c[i][x]*t;
            a[x]=v;
        }
        ll que(int l,int r){
            ll re=0;
            if(pos[l]==pos[r])
                for(int i=l;i<=r;i++) re+=A.fun(f[i]);
            else{
                for(int i=pos[l]+1;i<=pos[r]-1;i++) re+=sum[i];
                for(int i=l;i<=b[pos[l]].r;i++) re+=A.fun(f[i]);
                for(int i=b[pos[r]].l;i<=r;i++) re+=A.fun(f[i]);
            }
            return re;
        }
    }B;
    int main(){
        freopen("in","r",stdin);
        n=read();
        for(int i=1;i<=n;i++) a[i]=read(),s[i]=s[i-1]+a[i];
        for(int i=1;i<=n;i++) f[i].l=read(),f[i].r=read();
        iniBlock();B.ini();
        Q=read();
        while(Q--){
            op=read();x=read();y=read();
            if(op==1) B.cha(x,y);
            else printf("%llu
    ",B.que(x,y));
        }
    }
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define pii pair<int,int>
    #define MP make_pair
    #define fir first
    #define sec second
    const int N=1e5+5,M=350;
    typedef unsigned long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,Q,op,x,y;
    ll a[N];
    pii f[N];
    struct BIT{
        ll c[N];
        inline void add(int p,ll v){for(;p<=n;p+=(p&-p)) c[p]+=v;}
        inline ll sum(int p){ll re=0;for(;p;p-=(p&-p)) re+=c[p];return re;}
    }C;
    inline ll fun(int x){return C.sum(f[x].sec)-C.sum(f[x].fir-1);}
    struct _Block{int l,r;ll sum;};
    struct Block{
        int block,m,pos[N],c[M][N],s[N];
        _Block b[M];
        void ini(){
            block=sqrt(n); m=(n-1)/block+1;
            for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
    
            for(int i=1;i<=m;i++){
                b[i].l=(i-1)*block+1; b[i].r= i==m ? n : i*block;
                for(int j=b[i].l ; j<=b[i].r ; j++)
                    s[ f[j].fir ]++,s[ f[j].sec+1 ]--;
                int *cc=c[i];
                for(int j=1;j<=n;j++) cc[j]=cc[j-1]+s[j],b[i].sum+=cc[j]*a[j],s[j]=0;
            }
        }
        void cha(int x,ll v){
            v-=a[x];
            for(int i=1;i<=m;i++) b[i].sum+=c[i][x]*v;
            C.add(x,v); a[x]+=v;
        }
        ll que(int l,int r){
            ll re=0;
            if(pos[l]==pos[r])
                for(int i=l;i<=r;i++) re+=fun(i);
            else{
                for(int i=pos[l]+1;i<=pos[r]-1;i++) re+=b[i].sum;
                for(int i=l;i<=b[pos[l]].r;i++) re+=fun(i);
                for(int i=b[pos[r]].l;i<=r;i++) re+=fun(i);
            }
            return re;
        }
    }B;
    int main(){
        freopen("in","r",stdin);
        n=read();
        for(int i=1;i<=n;i++) a[i]=read(),C.add(i,a[i]);
        for(int i=1;i<=n;i++) f[i].fir=read(),f[i].sec=read();
        B.ini();
        Q=read();
        while(Q--){
            op=read();x=read();y=read();
            if(op==1) B.cha(x,y);
            else printf("%llu
    ",B.que(x,y));
        }
    }
    BIT
  • 相关阅读:
    树莓派设置音频输出音量
    linux下如何查询jdk的安装路径
    树莓派更新源集合
    树莓派wifi环境下初始化及环境配置
    JVM内存区域划分总结
    使用Mybatis Generator自动生成代码
    Clob类型转换为String
    树莓派3b+下一些常用的命令(Debian下)
    Leetcode 002-Search Insert Position
    Leetcode 001-twosum
  • 原文地址:https://www.cnblogs.com/candy99/p/6553299.html
Copyright © 2020-2023  润新知