数组分块入门 3

传送门

第一次用读入挂,感觉还行。

这题和数组分块2的题目差不多,只不过求的是最大前驱。

#include<bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
#define ll long long
int  a[maxn],belong[maxn],l[1005],r[1005],lazy[1005],block,num,n;
vector<int>v[1005];
inline ll read(){
	ll x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void build()
{
    memset(lazy,0,sizeof(lazy));
    block=sqrt(n);
    num=n/block;
    if(n%block) num++;
    for(int i=1;i<=num;i++)
        l[i]=(i-1)*block+1,r[i]=i*block;
    r[num]=n;
    for(int i=1;i<=n;i++)
    {
        belong[i]=(i-1)/block+1;
        v[belong[i]].push_back(a[i]);
    }
    for(int i=1;i<=num;i++)
        sort(v[i].begin(),v[i].end());
}
inline void reset(int x)
{
    v[x].clear();
    for(int i=l[x];i<=r[x];i++)
        v[x].push_back(a[i]);
    sort(v[x].begin(),v[x].end());
}
inline void update(int left,int right,int c)
{
    if(belong[left]==belong[right])
    {
        for(int i=left;i<=right;i++)
            a[i]+=c;
        reset(belong[left]);
    }
    else
    {
        for(int i=left;i<=r[belong[left]];i++)
            a[i]+=c;
        reset(belong[left]);
        for(int i=l[belong[right]];i<=right;i++)
            a[i]+=c;
        reset(belong[right]);
        for(int i=belong[left]+1;i<=belong[right]-1;i++)
            lazy[i]+=c;
    }
}
inline void query(int left,int right,int c)
{
    ll ans=-1e15;
    if(belong[left]==belong[right])
    {
        for(int i=left;i<=right;i++)
            if(a[i]+lazy[belong[i]]<c)
                ans=max(ans,(ll)(a[i]+lazy[belong[i]]));
    }
    else
    {
        for(int i=left;i<=r[belong[left]];i++)
            if(a[i]+lazy[belong[i]]<c)
                ans=max(ans,(ll)(a[i]+lazy[belong[i]]));
        for(int i=l[belong[right]];i<=right;i++)
            if(a[i]+lazy[belong[i]]<c)
                ans=max(ans,(ll)(a[i]+lazy[belong[i]]));
        for(int i=belong[left]+1;i<=belong[right]-1;i++)
        {
            int pos=lower_bound(v[i].begin(),v[i].end(),c-lazy[i])-v[i].begin();
            if(pos==0) continue;
            ans=max(ans,(ll)(v[i][pos-1]+lazy[i]));
        }
    }
    if(ans==(-1e15))
        cout<<-1<<endl;
    else
        cout<<ans<<endl;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    build();
    for(int i=1;i<=n;i++)
    {
        int opt,left,right,c;
        opt=read(),left=read(),right=read(),c=read();
        if(!opt)
            update(left,right,c);
        else
            query(left,right,c);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/eason9906/p/11754898.html