CDOJ-1929:一道普通题1(分块)



思路:分块。分成sqrt(n)个块,将每个块里的数存入vector中,排序。更新时,对于残缺的块,暴力更新即可,完整的块可以加懒惰标记;查询时类似,对于残缺的块暴力查找,完整的块利用二分。(代码有点丑。。)

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
typedef long long ll;
ll a[MAX],lazy[500];
int b[MAX],siz,cnt,n;
vector<ll>block[500];
void rebuild(int th)
{
    block[th].clear();
    for(int i=(th-1)*siz+1;i<=th*siz&&i<=n;i++)block[th].push_back(a[i]);
    sort(block[th].begin(),block[th].end());
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    siz=sqrt(n);
    cnt=n/siz;
    if(n%siz)cnt++;
    for(int i=1;i<=n;i++)
    {
        b[i]=(i-1)/siz+1;
        block[b[i]].push_back(a[i]);
    }
    for(int i=1;i<=cnt;i++)sort(block[i].begin(),block[i].end());
    for(int i=1;i<=n;i++)
    {
        int op,x,y,z;
        scanf("%d%d%d%d",&op,&x,&y,&z);
        if(op==0)
        {
            for(int j=x;j<=b[x]*siz&&j<=y;j++)a[j]+=z;
            rebuild(b[x]);
            for(int j=b[x]+1;j*siz<=n&&j*siz<=y;j++)lazy[j]+=z;
            if(b[x]!=b[y]&&y%siz)
            {
                for(int j=(b[y]-1)*siz+1;j<=y;j++)a[j]+=z;
                rebuild(b[y]);
            }
        }
        else
        {
            ll ans=-1;
            for(int j=x;j<=b[x]*siz&&j<=y;j++)
            {
                if(a[j]+lazy[b[x]]<z)ans=max(ans,a[j]+lazy[b[x]]);
            }
            for(int j=b[x]+1;j*siz<=y;j++)
            {
                int index=lower_bound(block[j].begin(),block[j].end(),z-lazy[j])-block[j].begin();
                if(index>0)ans=max(ans,block[j][index-1]+lazy[j]);
            }
            if(b[x]!=b[y]&&y%siz)
            {
                for(int j=(b[y]-1)*siz+1;j<=y;j++)
                {
                    if(a[j]+lazy[b[y]]<z)ans=max(ans,a[j]+lazy[b[y]]);
                }
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/mitsuha_/article/details/81046546
今日推荐