CDOJ-1928:帆宝RMQ(分块)


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

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
typedef long long ll;
int siz,cnt,n;
int b[MAX];
ll lazy[400];
struct lenka
{
    ll x,y;
}a[MAX];
vector<lenka>v[400];
int cmp(const lenka& p,const lenka& q)
{
    if(p.y==q.y)return p.x<q.x;
    return p.y<q.y;
}
void build()            //初始化建块
{
    siz=sqrt(n);
    cnt=n/siz;
    if(n%siz)cnt++;
    for(int i=1;i<=n;i++)
    {
        b[i]=(i-1)/siz+1;
        v[b[i]].push_back(a[i]);
    }
    for(int i=1;i<=cnt;i++)sort(v[i].begin(),v[i].end(),cmp);
}
void rebuild(int th)    //暴力更新残缺块
{
    v[th].clear();
    for(int i=(th-1)*siz+1;i<=th*siz&&i<=n;i++)v[th].push_back(a[i]);
    sort(v[th].begin(),v[th].end(),cmp);
}
int up(int th,int l,int r,ll x)//二分查找上限
{
    int ans=0;
    while(r>=l)
    {
        int mid=(l+r)/2;
        if(v[th][mid].y>x)r=mid-1;
        else
        {
            ans=mid;
            l=mid+1;
        }
    }
    if(v[th][ans].y==x)return v[th][ans].x;
    return -1;
}
int low(int th,int l,int r,ll x)//二分查找下限
{
    int ans=0;
    while(r>=l)
    {
        int mid=(l+r)/2;
        if(v[th][mid].y>=x)
        {
            ans=mid;
            r=mid-1;
        }
        else l=mid+1;
    }
    if(v[th][ans].y==x)return v[th][ans].x;
    return -1;
}
int main()
{
    int m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i].y);
        a[i].x=i;
    }
    build();
    while(m--)
    {
        int op;
        scanf("%d",&op);
        if(op==1)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            for(int i=x;i<=y&&i<=b[x]*siz;i++)a[i].y+=z;
            rebuild(b[x]);
            for(int i=b[x]+1;i*siz<=y;i++)lazy[i]+=z;
            if(b[x]!=b[y]&&y%siz)
            {
                for(int i=(b[y]-1)*siz+1;i<=y;i++)a[i].y+=z;
                rebuild(b[y]);
            }
        }
        else
        {
            ll x;
            scanf("%lld",&x);
            int l=-1,r=-2;
            for(int i=1;i<=cnt;i++)
            {
                int index=low(i,0,v[i].size()-1,x-lazy[i]);
                if(index!=-1)
                {
                    l=index;
                    break;
                }
            }
            for(int i=cnt;i>=1;i--)
            {
                int index=up(i,0,v[i].size()-1,x-lazy[i]);
                if(index!=-1)
                {
                    r=index;
                    break;
                }
            }
            printf("%d\n",r-l);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mitsuha_/article/details/81046971
RMQ