「CF551E」GukiZ and GukiZiana【分块】

题目链接

题意

  • 就是一个数组,两种操作,第一种区间加值,第二种查询某一个数在这个数组里的最远距离,比如数组1 2 1 2查询1的话答案就是2

题解

  • 考虑分块,将每块按照值升序,值相同按照在原数组的下标升序排序,每次加值的时候给llrr所在的块内的所有原位置为[l,r][l,r]的数加上这个值,然后将这两个块暴力sortsort,然后整块打上标记,查询的时候对每一个块二分查询

复杂度

  • O(nnlogn)O(n\sqrt n\log n)

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
const int smaxn=800;
int n,m,a[maxn],c,d,opt,x;

namespace blocking{
    int tot,belong[maxn],siz[smaxn],block;  //分块基本数据
    long long mark[maxn];                //解题数据
    pair<long long,int> v[maxn];
    void init(int n) {
        block=(int)sqrt((double)n);
        tot=n%block?(n/block+1):(n/block);
        for(int i=1;i<=n;i++) belong[i]=(i-1)/block+1;
        for(int i=1;i<=tot;i++) siz[i]=(min(i*block,n)-(i-1)*block);
    }
    void add(int l,int r,long long val) {
        if(belong[r]-belong[l]<=1) {
            for(int i=(belong[l]-1)*block+1;i<=min(belong[r]*block,n);i++) {
                if(v[i].second>=l&&v[i].second<=r) v[i].first+=val;
            }
            for(int i=belong[l];i<=belong[r];i++) sort(v+(i-1)*block+1,v+min(i*block,n)+1);
            return;
        }
        for(int i=(belong[l]-1)*block+1;i<=belong[l]*block;i++) {
            if(v[i].second<=r&&v[i].second>=l) v[i].first+=val;
        }
        sort(v+(belong[l]-1)*block+1,v+min(belong[l]*block,n)+1);
        for(int i=belong[l]+1;i<=belong[r]-1;i++) mark[i]+=val;
        for(int i=(belong[r]-1)*block+1;i<=min(belong[r]*block,n);i++) {
            if(v[i].second<=r&&v[i].second>=l) v[i].first+=val;
        }
        sort(v+(belong[r]-1)*block+1,v+min(belong[r]*block,n)+1);
    }

    int query(long long x) {
        int l=-1,r=-1;
        for(int i=1;i<=tot;i++) {
            int p=lower_bound(v+(i-1)*block+1,v+min(i*block,n)+1,make_pair(x-mark[i],0))-v;
            if(p<=min(i*block,n)&&v[p].first==x-mark[i]) {l=v[p].second;break;}
        }
        for(int i=tot;i>=1;i--) {
            int p=upper_bound(v+(i-1)*block+1,v+min(i*block,n)+1,make_pair(x-mark[i],n+1))-v;
            if(p>(i-1)*block+1&&v[p-1].first==x-mark[i]) {r=v[p-1].second;break;}
        }
        if(l==-1||r==-1) return -1;
        return r-l;
    }

    void debug() {
        printf("block= %d, tot= %d\n",block,tot);
        for(int i=1;i<=n;i++) printf("%d%c",belong[i],i==n?'\n':' ');
    }
}
using namespace blocking;

int main() {
    scanf("%d %d",&n,&m);init(n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),v[i]=make_pair(a[i],i);
    for(int i=1;i<=tot;i++) sort(v+(i-1)*block+1,v+min(i*block,n)+1);
    for(int i=1;i<=m;i++) {
        scanf("%d",&opt);
        if(opt==1) {
            scanf("%d %d %d",&c,&d,&x);
            add(c,d,x);
        }else {
            scanf("%d",&x);
            printf("%d\n",query(x));
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章