分块学习ing

感觉这个不算科技吧,就是现在把操作降在块内了,算是暴力的优化

https://loj.ac/problem/6277

LOJ6277. 数列分块入门 1

对于这些数你有两种操作,0是区间+,1是区间查询

#include<bits/stdc++.h>
using namespace std;
#define N 50005
int m,belong[N];
int a[N],tag[N];
void change(int l,int r,int val)
{
    for(int i=l;i<=min(r,belong[l]*m);i++) a[i]+=val;//将a块内剩余部分暴力更新
    if(belong[l]!=belong[r])
    {
        for(int i=(belong[r]-1)*m+1;i<=r;i++) a[i]+=val;//将b块内剩余部分暴力更新
    }
    for(int i=belong[l]+1;i<=belong[r]-1;i++)tag[i]+=val;//将整块需要加的值更新上去
}
int main()
{
    int n;
    scanf("%d",&n);
    m=sqrt(n);//一块有几个
    for(int i=1;i<=n;i++) belong[i]=(i-1)/m+1;//将每个值分到所给的块内
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1,op,l,r,val;i<=n;i++)
    {
        scanf("%d%d%d%d",&op,&l,&r,&val);
        if(!op)change(l,r,val);
        else printf("%d\n",tag[belong[r]]+a[r]);//tag获取这个序列被加的值
    }
    return 0;
}

LOJ6278. 数列分块入门 2

这个还是区间加,但是要查询区间小于c*c的值

这个就麻烦多了,还要排序的啊

#include<bits/stdc++.h>
using namespace std;
#define N 50005
int n,m,belong[N];
int a[N],tag[N];
vector<int>vec[N];
void reset(int x)
{
    //将两个特殊的块更新
    vec[x].clear();
    for(int i=(x-1)*m+1; i<=min(x*m,n); i++)vec[x].push_back(a[i]);
    sort(vec[x].begin(),vec[x].end());
}
void change(int l,int r,int val)
{
    for(int i=l; i<=min(r,belong[l]*m); i++) a[i]+=val; //将a块内剩余部分暴力更新
    reset(belong[l]);
    if(belong[l]!=belong[r])
    {
        for(int i=(belong[r]-1)*m+1; i<=r; i++) a[i]+=val; //将b块内剩余部分暴力更新
        reset(belong[r]);
    }
    for(int i=belong[l]+1; i<=belong[r]-1; i++)tag[i]+=val; //将整块需要加的值更新上去
}
int query(int l,int r,int val)
{
    int ans=0;
    for(int i=l; i<=min(belong[l]*m,r); i++)if(a[i]+tag[belong[l]]<val)ans++;
    if(belong[l]!=belong[r])
        for(int i=(belong[r]-1)*m+1; i<=r; i++)if(a[i]+tag[belong[r]]<val)ans++;
    for(int i=belong[l]+1; i<=belong[r]-1; i++)
        ans+=lower_bound(vec[i].begin(),vec[i].end(),val-tag[i])-vec[i].begin();
    return ans;
}
int main()
{
    scanf("%d",&n);
    m=sqrt(n);//一块有几个
    for(int i=1; i<=n; i++)belong[i]=(i-1)/m+1; //将每个值分到所给的块内
    for(int i=1; i<=n; i++)scanf("%d",&a[i]),vec[belong[i]].push_back(a[i]);
    for(int i=1;i<=belong[n];i++)sort(vec[i].begin(),vec[i].end());//每块要先保证有序,因为以后不再更新了
    for(int i=1,op,l,r,val; i<=n; i++)
    {
        scanf("%d%d%d%d",&op,&l,&r,&val);
        if(!op)change(l,r,val);
        else printf("%d\n",query(l,r,val*val));
    }
    return 0;
}

这个上面改改就行了

#include<bits/stdc++.h>
using namespace std;
#define N 100005
int n,m,belong[N];
int a[N],tag[N];
vector<int>vec[N];
void reset(int x)
{
    //将两个特殊的块更新
    vec[x].clear();
    for(int i=(x-1)*m+1; i<=min(x*m,n); i++)vec[x].push_back(a[i]);
    sort(vec[x].begin(),vec[x].end());
}
void change(int l,int r,int val)
{
    for(int i=l; i<=min(r,belong[l]*m); i++) a[i]+=val; //将a块内剩余部分暴力更新
    reset(belong[l]);
    if(belong[l]!=belong[r])
    {
        for(int i=(belong[r]-1)*m+1; i<=r; i++) a[i]+=val; //将b块内剩余部分暴力更新
        reset(belong[r]);
    }
    for(int i=belong[l]+1; i<=belong[r]-1; i++)tag[i]+=val; //将整块需要加的值更新上去
}
int query(int l,int r,int val)
{
    int ans=-1;
    for(int i=l; i<=min(belong[l]*m,r); i++)if(a[i]+tag[belong[l]]<val)ans=max(ans,a[i]+tag[belong[l]]);
    if(belong[l]!=belong[r])
        for(int i=(belong[r]-1)*m+1; i<=r; i++)if(a[i]+tag[belong[r]]<val)ans=max(ans,a[i]+tag[belong[r]]);
    for(int i=belong[l]+1,pos; i<=belong[r]-1; i++)
    {
        pos=lower_bound(vec[i].begin(),vec[i].end(),val-tag[i])-vec[i].begin();
        if(pos>=1) ans=max(ans,vec[i][pos-1]+tag[i]);
    }
    return ans;
}

int main()
{
    scanf("%d",&n);
    m=sqrt(n);//一块有几个
    for(int i=1; i<=n; i++)belong[i]=(i-1)/m+1; //将每个值分到所给的块内
    for(int i=1; i<=n; i++)scanf("%d",&a[i]),vec[belong[i]].push_back(a[i]);
    for(int i=1;i<=belong[n];i++)sort(vec[i].begin(),vec[i].end());//每块要先保证有序,因为以后不更新了
    for(int i=1,op,l,r,val; i<=n; i++)
    {
        scanf("%d%d%d%d",&op,&l,&r,&val);
        if(!op)change(l,r,val);
        else printf("%d\n",query(l,r,val));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/BobHuang/p/9632901.html
ing
今日推荐