題目鏈接
題意
- 就是一個數組,兩種操作,第一種區間加值,第二種查詢某一個數在這個數組裏的最遠距離,比如數組1 2 1 2查詢1的話答案就是2
題解
- 考慮分塊,將每塊按照值升序,值相同按照在原數組的下標升序排序,每次加值的時候給l和r所在的塊內的所有原位置爲[l,r]的數加上這個值,然後將這兩個塊暴力sort,然後整塊打上標記,查詢的時候對每一個塊二分查詢
複雜度
- O(nnlogn)
代碼
#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));
}
}
}