数列分块

数列分块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));
    }
}
原文地址:https://www.cnblogs.com/MikuKnight/p/8998520.html