zoukankan      html  css  js  c++  java
  • 数列分块

    数列分块1

    //分块后在块内二分,两边暴力处理 
    
    #include<cstdio>
    #include<cctype>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int n,block,tot,belong[50002],r[250],a[50002],b[50002],ad[250];
    
    inline void read(int &x){
        char ch=getchar();x=0;int f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        x*=f;
    }
    
    void reset(int whic){
        for(int i=r[whic-1]+1;i<=r[whic];i++)b[i]=a[i];
        sort(b+r[whic-1]+1,b+r[whic]);
    }
    
    void add(int x,int y,int c){
        int lb=belong[x],rb=belong[y];
        if(lb==rb){
            for(register int i=x;i<=y;i++)a[i]+=c;
            reset(lb);
            return;
        }
        if(x%block!=1){
            for(register int i=x;i<=r[belong[x]];i++)a[i]+=c;
            reset(lb);
            lb++;
        }
        if(y%block>0){
            for(register int i=r[belong[y]-1]+1;i<=y;i++)a[i]+=c;
            reset(rb);
            rb--;
        }
        for(register int i=lb;i<=rb;i++)ad[i]+=c;
    }
    
    int query(int x,int y,int c){
        int lb=belong[x],rb=belong[y];
        int ans=0;
        if(lb==rb){
            for(register int i=x;i<=y;i++)if(a[i]+ad[belong[x]]<c)ans++;
            return ans;
        }
        if(x%block!=1){
            for(register int i=x;i<=r[belong[x]];i++)if(a[i]+ad[belong[x]]<c)ans++;
            lb++;
        }
        if(y%block>0){
            for(register int i=r[belong[y]-1]+1;i<=y;i++)
            if(a[i]+ad[belong[y]]<c)ans++;
            rb--;
        }
        for(int i=lb;i<=rb;i++){
        ans=ans+lower_bound(b+r[i-1]+1,b+r[i],c-ad[i])-b-r[i-1]-1;//被lower_bound处理卡了两天。。。 
        if(c-ad[i]>b[r[i]])ans++;//因为若数组最后一个数仍小于寻找的数,返回的是最后一个位置,未将最后一个数算进去 
        }return ans;
        
    }
    
    inline void putans(int x){
        if(x>=10)putans(x/10);putchar('0'+x%10);return;
    }
    
    int main(){
        read(n);block=sqrt(n);
        for(register int i=1;i<=n;i++){
            read(a[i]);
            belong[i]=tot;
            if(i%block==1){r[tot]=i-1;belong[i]=++tot;}
        }
        b[0]=a[0]=-1000000;
        r[tot]=n;
        for(int i=1;i<=tot;i++)reset(i);
        for(register int i=1;i<=n;i++){
            int opt,x,y,c;
            read(opt);read(x);read(y);read(c);
            if(opt==0)add(x,y,c);else printf("%d\n",query(x,y,c*c));
        }
    }

    数列分块2

    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #include<set>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    int n,block,tot,a[100002],belong[100002],r[350],ad[350];
    set<int>st[350];
    
    inline void read(int&x){
        char ch=getchar();x=0;int f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        x*=f;
    }
    
    void add(int x,int y,int c){
        int lb=belong[x],rb=belong[y];
        if(lb==rb){
            for(int i=x;i<=y;i++){
                st[lb].erase(a[i]);a[i]+=c;st[lb].insert(a[i]);
            }
            return;
        }
        if(x%block!=1){
            for(int i=x;i<=r[lb];i++){
                st[lb].erase(a[i]);a[i]+=c;st[lb].insert(a[i]);
            }
            lb++;
        }
        if(y%block>0){
            for(int i=r[rb-1]+1;i<=y;i++){
                st[rb].erase(a[i]);a[i]+=c;st[rb].insert(a[i]);
            }
            rb--;
        }
        for(int i=lb;i<=rb;i++)ad[i]+=c;
    }
    
    int query(int x,int y,int c){
        int ans=-1,lb=belong[x],rb=belong[y];
        if(lb==rb){
            for(int i=x;i<=y;i++)if(a[i]+ad[lb]<c)ans=max(ans,a[i]+ad[lb]);
            return ans;
        }
        if(x%block!=1){
            for(int i=x;i<=r[lb];i++)if(a[i]+ad[lb]<c)ans=max(ans,a[i]+ad[lb]);
            lb++;
        }
        if(y%block>0){
            for(int i=r[rb-1]+1;i<=y;i++)if(a[i]+ad[rb]<c)ans=max(ans,a[i]+ad[rb]);
            rb--;
        }
        for(int i=lb;i<=rb;i++){
            set<int>::iterator it=st[i].lower_bound(c-ad[i]);
            if(it!=st[i].begin()){
                it--;
                ans=max(ans,*it+ad[i]);
            }
        }
        return ans;
    }
    
    int main(){
        read(n);block=sqrt(n);
        for(int i=1;i<=n;i++){
            read(a[i]);
            if(i%block==1)r[tot]=tot*block,belong[i]=++tot;else belong[i]=tot;
            st[belong[i]].insert(a[i]);
        }
        r[tot]=n;
        for(int i=1;i<=n;i++){
            int opt,x,y,c;
            read(opt);read(x);read(y);read(c);
            if(opt==0)add(x,y,c);else printf("%d\n",query(x,y,c));
        }
    }

    数列分块3

    #include<cstdio>
    #include<cctype>
    #include<cmath>
    using namespace std;
    int n,block,tot;
    long long a[50002],belong[50002],r[250],ad[250];
    long long sum[250];
    
    inline void read(int &x){
        char ch=getchar();x=0;int f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        x*=f;
    }
    
    inline void read(long long &x){
        char ch=getchar();x=0;int f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        x*=f;
    }
    
    inline void add(int x,int y,int c){
        int lb=belong[x],rb=belong[y];
        if(lb==rb){
            for(int i=x;i<=y;i++)a[i]+=c;
            sum[lb]=sum[lb]+(y-x+1)*c;
            return;
        }
        if(x%block!=1){
            for(int i=x;i<=r[lb];i++)a[i]+=c;
            sum[lb]=sum[lb]+(r[lb]-x+1)*c;
            lb++;
        }
        if(y%block>0){
            for(int i=r[rb-1]+1;i<=y;i++)a[i]+=c;
            sum[rb]=sum[rb]+(y-r[rb-1])*c;
            rb--;
        }
        for(int i=lb;i<=rb;i++)ad[i]+=c;
    }
    
    inline int query(int x,int y,int c){
        long long ans=0;
        int lb=belong[x],rb=belong[y];
        if(lb==rb){
            ans=(y-x+1)*ad[lb]%(c+1);
            for(int i=x;i<=y;i++)ans=(ans+a[i])%(c+1);
            return ans;
        }
        if(x%block!=1){
            for(int i=x;i<=r[lb];i++)ans=(ans+a[i])%(c+1);
            ans=(ans+(r[lb]-x+1)*ad[lb]%(c+1))%(c+1);
            lb++;
        }
        if(y%block>0){
            for(int i=r[rb-1]+1;i<=y;i++)ans=(ans+a[i])%(c+1);
            ans=(ans+(y-r[rb-1])*ad[rb]%(c+1))%(c+1);
            rb--;
        }
        for(int i=lb;i<=rb;i++)ans=(ans+sum[i]+ad[i]*(r[i]-r[i-1])%(c+1))%(c+1);
        return ans;
    }
    
    int main(){
        read(n);block=sqrt(n);
        for(int i=1;i<=n;i++){
            read(a[i]);
            if(i%block==1){r[tot]=i-1;belong[i]=++tot;}else belong[i]=tot;
            sum[belong[i]]+=a[i];
        }
        for(int i=1;i<=n;i++){
            int opt,x,y,c;
            read(opt);read(x);read(y);read(c);
            if(opt==0)add(x,y,c);else printf("%d\n",query(x,y,c));
        }
    }
  • 相关阅读:
    Windows 7 语音识别和屏幕录像
    用户体验研究乱谈后台导航
    安装VS2010
    lucene.net搜索索引详解
    网站秒杀那点破事
    初次给鼠标手术
    网站页面回车和鼠标焦点
    利用C语言的部分初始化特性进行字符串的全部初始化。
    QoS的各个方面
    指针和数组错用的问题汇总
  • 原文地址:https://www.cnblogs.com/MikuKnight/p/8998520.html
Copyright © 2011-2022 走看看