LibreOJ 6279 数列分块入门 3(分块+排序)

题解:自然是先分一波块,把同一个块中的所有数字压到一个vector中,将每一个vector进行排序.然后对于每一次区间加,不完整的块加好后暴力重构,完整的块直接修改标记.查询时不完整的块暴力找最接近x的解,完整的块用二分查找,其实还可以用set维护,出于对最暴力AC的尊敬,我并没有这么写.照样过了.

代码如下:

#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int tag[100010],a[100010],lump[100010];
int sz,n;
vector<int> v[1010];

void reset(int x)
{
    v[x].clear();
    for(int i=(x-1)*sz+1; i<=min(x*sz,n); i++)
    {
        v[x].push_back(a[i]);
    }
    sort(v[x].begin(),v[x].end());
}

void add(int l,int r,int c)
{
    for(int i=l; i<=min(lump[l]*sz,r); i++)
    {
        a[i]+=c;
    }
    reset(lump[l]);
    if(lump[l]!=lump[r])
    {
        for(int i=(lump[r]-1)*sz+1; i<=r; i++)
        {
            a[i]+=c;
        }
        reset(lump[r]);
    }
    for(int i=lump[l]+1; i<=lump[r]-1; i++)
    {
        tag[i]+=c;
    }
}

int query(int l,int r,int x)
{
    int ans=-1;
    for(int i=l; i<=min(lump[l]*sz,r); i++)
    {
        if(a[i]+tag[lump[i]]>ans&&x>a[i]+tag[lump[i]])
        {
            ans=a[i]+tag[lump[i]];
        }
    }
    if(lump[l]!=lump[r])
    {
        for(int i=(lump[r]-1)*sz+1; i<=r; i++)         //!!!
        {
            if(tag[lump[i]]+a[i]>ans&&x>a[i]+tag[lump[i]])
            {
                ans=a[i]+tag[lump[i]];
            }
        }
    }
    for(int i=lump[l]+1; i<=lump[r]-1; i++)
    {
        int gg=x-tag[i];
        int pos=lower_bound(v[i].begin(),v[i].end(),gg)-v[i].begin();
        if(pos!=0)
        {
            int w=v[i][pos-1];
            if(w+tag[i]>ans&&w+tag[i]<x)
            {
                ans=w+tag[i];
            }
        }

    }
    return ans;
}

int main()
{
    int opt,l,r,c;
    scanf("%d",&n);
    sz=sqrt(n);
    for(int i=1; i<=n; i++)
    {
        lump[i]=(i-1)/sz+1;
    }
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        v[lump[i]].push_back(a[i]);
    }
    for(int i=1; i<=lump[n]; i++)
    {
        sort(v[i].begin(),v[i].end());
    }
    for(int i=1; i<=n; i++)
    {
        scanf("%d%d%d%d",&opt,&l,&r,&c);
        if(!opt)
        {
            add(l,r,c);
        }
        else
        {
            printf("%d
",query(l,r,c));
        }
    }
}
原文地址:https://www.cnblogs.com/stxy-ferryman/p/8560088.html