分块见习

分块初始化:

int a[50005];//原始序列
int l[2000];//第i个块的左区间端点
int r[2000];//第i个块的右区间端点
int pos[50005];//第i个点属于第几个块
 
int n;
scanf("%d",&n);
int dis=sqrt(n);//每一块的大小
int num=ceil(n*1.0/dis);//分块数目
for(int i=1;i<=num;i++)
{
    l[i]=(i-1)*dis+1;//第i个块的左区间端点
    r[i]=i*dis;//第i个块的右区间端点
}
r[num]=n;//最后一个块的右端点最大等于n
for(int i=1;i<=n;i++)
{
    scanf("%d",&a[i]);
    pos[i]=(i-1)/dis+1;//第i个数属于第几个块
}
View Code

题:https://loj.ac/problem/6278

题意:支持区间加,求区间小于c*c的个数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int M=5e4+4;
int a[M],b[M],pos[M],l[M],r[M],lz[M];
void init(int n){
    int dis=sqrt(n);
    int num=ceil(n*1.0/dis);
    for(int i=1;i<=num;i++){
        l[i]=(i-1)*dis+1;
        r[i]=i*dis;
    }
    r[num]=n;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        pos[i]=(i-1)/dis+1;
        b[i]=a[i];
    }
    for(int i=1;i<=num;i++)
        sort(b+l[i],b+r[i]+1);
}
void add(int L,int R,int v){
    int posl=pos[L],posr=pos[R];
    if(posl==posr){
        for(int i=L;i<=R;i++)
            a[i]+=v;
        for(int i=l[posl];i<=r[posl];i++)
            b[i]=a[i];
        sort(b+l[posl],b+r[posl]+1);
    }
    else{
        ///left
        for(int i=L;i<=r[posl];i++)
            a[i]+=v;
        for(int i=l[posl];i<=r[posl];i++)
            b[i]=a[i];
        sort(b+l[posl],b+r[posl]+1);
        ///mid
        for(int i=posl+1;i<posr;i++)
            lz[i]+=v;
        ///right
        for(int i=l[posr];i<=R;i++)
            a[i]+=v;
        for(int i=l[posr];i<=r[posr];i++)
            b[i]=a[i];
        sort(b+l[posr],b+r[posr]+1);
    }
}
int query(int L,int R,int c){
    int posl=pos[L],posr=pos[R];
    int cnt=0;
    if(posl==posr){
        for(int i=L;i<=R;i++)
            if(a[i]<c-lz[posl])
                cnt++;
        return cnt;
    }
    ///left
    for(int i=L;i<=r[posl];i++)
        if(a[i]<c-lz[posl])
            cnt++;
    ///right
    for(int i=l[posr];i<=R;i++)
        if(a[i]<c-lz[posr])
            cnt++;
    ///mid
    for(int i=posl+1;i<posr;i++)
        cnt+=lower_bound(b+l[i],b+r[i]+1,c-lz[i])-(b+l[i]);
    return cnt;
}
int main(){
    int n;
    scanf("%d",&n);
    init(n);

    for(int i=1;i<=n;i++){
        int op,x,y,c;
        scanf("%d%d%d%d",&op,&x,&y,&c);
        if(op==0)
            add(x,y,c);
        else
            printf("%d
",query(x,y,c*c));
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/starve/p/12830063.html