zoukankan      html  css  js  c++  java
  • bzoj3188 [Coci 2011]Upit(分块)

    Time Limit: 10 Sec  Memory Limit: 128 MB

    Description

    你需要维护一个序列,支持以下4种操作。一,将区间(u,v)的数覆盖为C;二,
    将区间(u,v)的数依次加上一个以C为首项、C为公差的等差数列;三,将数C插入
    第i个位置;四,查询区间(u,v)的数的和。序列最初有n个数,一共会有Q次操
    作。保证结果在longlong范围内。 
     

    Sample Input

    5 5
    1 2 3 4 5
    1 5 5 0
    4 4 5
    4 5 5
    2 1 5 1
    4 1 5

    Sample Output

    4
    0
    25

    HINT

    n, Q <= 100,000. 


    我非常喜欢分块,所以我用分块过了这题
    支持插入,区间加,修改的分块,用vector数组维护打打标记就行了
    如果某块过大,暴力拆成两块就好辣(数据挺水好像用不上)
    代码中块和数列的编号均从0开始
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<algorithm>
    #define ri register int
    using namespace std;
    typedef long long ll;
    ll read(){
        char c=getchar(); ll x=0; bool f=1;
        while(c<'0'||c>'9') f=f&&(c!='-'),c=getchar();
        while('0'<=c&&c<='9') x=x*10+c-48,c=getchar();
        return f?x:-x;
    }
    #define N 60005
    int n,Q,idm,B,sm[N];
    ll s[N],w[N],d[N],k[N];
    bool a[N],b[N];
    vector <int> h; //从左到右块的编号
    vector <ll> g[N];
    inline ll G(int x){return g[x].size();}
    inline int id(int x){return lower_bound(sm+1,sm+idm+1,x)-sm-1;}//x属于哪个块
    void down(int x){
        if(a[x]) s[x]=G(x)*w[x],g[x].assign(G(x),w[x]),a[x]=w[x]=0;
        if(b[x]){
            ll q=d[x],q2=k[x],t=0; b[x]=k[x]=d[x]=s[x]=0;
            for(ri i=0;i<G(x);++i) t+=q,g[x][i]+=t+q2,s[x]+=g[x][i];
        }
    }
    void cover(int x,int y,ll v){
        ri ix=id(x),iy=id(y),L=h[ix],R=h[iy],l=x-sm[ix]-1,r=y-sm[iy]-1;
        if(L==R){
            down(L);
            for(ri i=l;i<=r;++i) s[L]+=(v-g[L][i]),g[L][i]=v;
            return ;
        }down(L),down(R);
        for(ri i=l;i<G(L);++i) s[L]+=(v-g[L][i]),g[L][i]=v;
        for(ri j=ix+1,i;j<iy;++j) i=h[j],s[i]=v*G(i),b[i]=k[i]=d[i]=0,w[i]=v,a[i]=1;
        for(ri i=0;i<=r;++i) s[R]+=(v-g[R][i]),g[R][i]=v;
    }
    void add(int x,int y,ll v){
        ri ix=id(x),iy=id(y),L=h[ix],R=h[iy],l=x-sm[ix]-1,r=y-sm[iy]-1; ll q=0;
        if(L==R){
            down(L);
            for(ri i=l;i<=r;++i) q+=v,s[L]+=q,g[L][i]+=q;
            return ;
        }down(L),down(R);
        for(ri i=l;i<G(L);++i) q+=v,s[L]+=q,g[L][i]+=q;
        for(ri j=ix+1,i;j<iy;++j){
            i=h[j];
            if(a[i]){
                s[i]=G(i)*w[i];
                if(b[i]) s[i]+=(d[i]+d[i]*G(i))*G(i)/2+k[i]*G(i);
            }
            s[i]+=(v+v*G(i))*G(i)/2+q*G(i); 
            b[i]=1; d[i]+=v; k[i]+=q; q+=v*G(i);
        }
        for(ri i=0;i<=r;++i) q+=v,s[R]+=q,g[R][i]+=q;
    }
    void split(int x){
        ri ix=id(x),L=h[ix];
        h.insert(h.begin()+ix+1,idm);
        for(ri i=B;i<G(L);++i)
            g[idm].push_back(g[L][i]),s[idm]+=g[L][i],s[L]-=g[L][i];
        g[L].erase(g[L].begin()+B,g[L].end()); idm++;
    }
    void ins(int x,ll v){
        ri ix=id(x),L=h[ix],l=x-sm[ix]-1;
        down(L); g[L].insert(g[L].begin()+l,v); s[L]+=v;
        if(G(L)>B*2) split(x);//暴力拆块
        for(ri i=0;i<idm;++i) sm[i+1]=sm[i]+G(h[i]);
    }
    ll ask(int x,int y){
        ri ix=id(x),iy=id(y),L=h[ix],R=h[iy],l=x-sm[ix]-1,r=y-sm[iy]-1; ll re=0;
        if(L==R){
            down(L);
            for(ri i=l;i<=r;++i) re+=g[L][i];
            return re;
        }down(L),down(R);
        for(ri i=l;i<G(L);++i) re+=g[L][i];
        for(ri j=ix+1;j<iy;++j) re+=s[h[j]];
        for(ri i=r;i>=0;--i) re+=g[R][i];
        return re;
    }
    int main(){
        n=read(),Q=read(); ll q,x,y; sm[0]=-1; B=sqrt(n);
        for(ri i=0;i<n;++i) q=read(),g[i/B].push_back(q),s[i/B]+=q;
        while(idm*B<=n) sm[idm+1]=sm[idm]+G(idm),h.push_back(idm++);//sm[i]:第$i-1$块的右端点
        while(Q--){
            q=read(),x=read(),y=read();
            if(q==1) cover(x-1,y-1,read());
            if(q==2) add(x-1,y-1,read());
            if(q==3) ins(x-1,y);
            if(q==4) printf("%lld
    ",ask(x-1,y-1));
        }return 0;
    }
  • 相关阅读:
    null和undefined的区别
    百度小程序组件引用问题
    hbase优化操作与建议
    Hbase Rowkey设计原则
    kafka容器报内存不足异常(failed; error='Cannot allocate memory' (errno=12))
    Hbase安装
    四、hive安装
    一、linux安装mysql
    三、hadoop、yarn安装配置
    linux下磁盘进行分区、文件系统创建、挂载和卸载
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/11518020.html
Copyright © 2011-2022 走看看