「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));
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章